Featured Post

Applying Email Validation to a JavaFX TextField Using Binding

This example uses the same controller as in a previous post but adds a use case to support email validation.  A Commons Validator object is ...

Tuesday, September 13, 2016

Disabling a Save Button with JavaFX Confirmation Binding Controls

This post demonstrates a one-line JavaFX Binding expression that disables a Save Button until a confirmed input is entered into a pair of TextFields.

btnSave.disableProperty().bind(
    txtEmail.textProperty().isEqualTo(txtConfirmEmail.textProperty()).not()
    .or(
        txtEmail.textProperty().isEmpty()
    )
);



This video shows the enabling and disabling of the Save Button through entering and removing text from the Email and Confirm Email Text Fields.



In SceneBuilder, I added a pair of TextFields, txtEmail and txtConfirmEmail, to a GridPane.

Scene Builder Showing Confirm Screen
This JavaFX Controller binds the disable (not disabled) property of the Save button to a compound expression.  The or() method is used to disable the Save button under two conditions


  1. The contents of the TextFields are not equal.  Notice the not() method at the end of the isEqualTo() method.
  2. The txtEmail TextField is empty.  This is a case enforcing the required field.

The binding expression is put in the @FXML initialize() method.

public class ConfirmController {

    private Logger logger = Logger.getLogger("ConfirmController");

    @FXML
    private TextField txtEmail, txtConfirmEmail;

    @FXML
    private GridPane gridPane;

    @FXML
    private Button btnSave;

    @FXML
    public void initialize() {

        btnSave.disableProperty().bind(
                txtEmail.textProperty().isEqualTo(txtConfirmEmail.textProperty()).not()
                .or(
                       txtEmail.textProperty().isEmpty()
                )
        );
    }

    @FXML
    public void save(ActionEvent evt) {
        logger.info("confirmed " + txtEmail.getText());
        hide(evt);
    }

    @FXML
    public void cancel(ActionEvent evt) {
        hide(evt);
    }

    private void hide(ActionEvent evt) {
        ((Node)evt.getSource()).getScene().getWindow().hide();
    }
}

While you can satisfy this requirement using property listeners as you might do with a Swing program, this JavaFX Binding syntax will be more consistent in your app.  That's because there's more variation in listeners: lambda vs anonymous inner class, parameter names, variations on comparisons and empty checks.  Once you get up the learning curve of JavaFX Binding, this type of expression becomes very

11 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. btnSave.disableProperty().bind( bp1 ) or btSave.disableProperty().bind( bp1.not() ) depending on your logic

    ReplyDelete
    Replies
    1. we familar with this tfUserName.textProperty().isEmpty() , but if we want to take a boolean value TRUE OR FALSE instead of above

      bp1.stringProperty().

      Delete
    2. Something like this creates an anonymous binding. This wont'b be that useful since a change in myBool won't update the anonymous object (SimpleBooleanProperty) and hence won't update the disabled property.

      boolean myBool = false;

      btnSave.disableProperty().bind( new SimpleBooleanProperty(myBool) );

      It sound like you should focus on setting bp1 with your business logic using the set() method. That way, any bindings will automatically update the UI.

      Good luck!

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. hi carl

    how should do with booleanProperty value true false , to disableBinding

    private BooleanProperty bp1;

    p v initialize(){
    bp1 = new SimpleBooleanProperty(false);
    mybutton.disableProperty().bind(getSaveButtonDisabledBinding1());
    }
    BooleanBinding getSaveButtonDisabledBinding1()
    {
    return
    bp1.getValue. // here it taking boolean true n false , how to do
    }

    ReplyDelete
  5. Something like this?

    private BooleanProperty bp1;
    private Button save_b;

    private void initialize() {
    save_b.disableProperty().bind( bp1 );
    }

    private void save(ActionEvent evt) {
    bp1.set( true );
    doSave(); // alternate: put in a Task
    bp1.set( false ); // alternate: put in a Task.succeeded() method
    }

    ReplyDelete
    Replies
    1. //bp1= new SimpleBooleanProperty(fasle);
      // and bp1 was instantiated true some where where below BooleanBinding takes true value and binds to disableBinding
      BooleanBinding getSaveButtonDisabledBinding2()
      {
      return
      bp1.booleanProperty(bp1).isEqualTo(other) // not working
      }

      Delete
    2. and i took
      public ReadOnlyBooleanProperty bp1Status()
      {
      return this.bp1;
      }

      Delete
    3. Let's break this down a little...Does this work for you with hardcoded values?

      BooleanProperty bp1 = new BooleanProperty(true);
      BooleanProperty other = new BooleanProperty(true);

      save_b.disableProperty( bp1.isEqualTo().bind( other ) )

      If so, try the other four combinations to make sure we're in sync (false/false, false/true, true/false).

      Delete
    4. Thanks Carl
      finally it works by taking two boolean variables, but it takes to hardcodng

      this.bp0 = new SimpleBooleanProperty(false);
      this.bp1 = new SimpleBooleanProperty(true);

      System.out.println("USerController | initialize()");

      this.saveUserButton.disableProperty().bind(getSaveButtonDisabledBinding1());
      //this.saveUserButton.disableProperty().bind(getSaveButtonDisabledBinding2());

      //this.updateUserButton.disableProperty().bind(getSaveButtonDisabledBinding2());
      this.deleteUserButton.disableProperty().bind(bp0.isEqualTo(bp1));

      Delete