JavaFX - question regarding binding button's disabled state

Posted by jamiebarrow on Stack Overflow See other posts from Stack Overflow or by jamiebarrow
Published on 2010-05-27T07:50:05Z Indexed on 2010/05/27 7:51 UTC
Read the original article Hit count: 292

I'm trying to create a dummy application that maintains a list of tasks.

For now, all I'm trying to do is add to the list. I enter a task name in a text box, click on the add task button, and expect the list to be updated with the new item and the task name input to be cleared. I only want to be able to add tasks if the task name is not empty. The below code is my implementation, but I have a question regarding the binding.

I'm binding the textbox's text variable to a string in my view model, and the button's disable variable to a boolean in my view model.

I have a trigger to update the disabled state when the task name changes. When the binding of the task name happens the boolean is updated accordingly, but the button still appears disabled. But then when I mouse over the button, it becomes enabled. I believe this is due to JavaFX 1.3's binding being lazy - only updates the bound variable when it is read.

Also, when I've added the task, I clear the task name in the model, but the textbox's text doesn't change - even though I'm using bind with inverse.

Is there a way to make the textbox's text and the button's disabled state update automatically via the binding as I was expecting?

Thanks,

James

AddTaskViewModel.fx:

package jamiebarrow;

import java.lang.System;

public class AddTaskViewModel {

function logChange(prop:String,oldValue,newValue):Void {
    println("{System.currentTimeMillis()} : {prop} [{oldValue}] to [{newValue}] ");
}


    public var newTaskName: String on replace old {
        logChange("newTaskName",old,newTaskName);
        isAddTaskDisabled = (newTaskName == null or newTaskName.trim().length() == 0);
    };
    public var isAddTaskDisabled: Boolean on replace old {
        logChange("isAddTaskDisabled",old,isAddTaskDisabled);
    };
    public var taskItems = [] on replace old {
        logChange("taskItems",old,taskItems);
    };

    public function addTask() {
        insert newTaskName into taskItems;
        newTaskName = "";
    }

}

Main.fx:

package jamiebarrow;

import javafx.scene.control.Button;
import javafx.scene.control.TextBox;
import javafx.scene.control.ListView;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.layout.HBox;

def viewModel = AddTaskViewModel{};

var txtName: TextBox = TextBox {
            text: bind viewModel.newTaskName with inverse
            onKeyTyped: onKeyTyped
        };

function onKeyTyped(event): Void {
    txtName.commit(); // ensures model is updated
    cmdAddTask.disable = viewModel.isAddTaskDisabled;// the binding only occurs lazily, so this is needed
}

var cmdAddTask = Button {
            text: "Add"
            disable: bind viewModel.isAddTaskDisabled with inverse
            action: onAddTask
        };

function onAddTask(): Void {
    viewModel.addTask();
}

var lstTasks = ListView {
            items: bind viewModel.taskItems with inverse
        };

Stage {
    scene: Scene {
        content: [
            VBox {
                content: [
                    HBox {
                        content: [
                            txtName,
                            cmdAddTask
                        ]
                    },
                    lstTasks
                ]
            }
        ]
    }
}

© Stack Overflow or respective owner

Related posts about binding

Related posts about javafx