iShareHappyCode
iShareHappyCode

Reputation: 255

Updating dynamically generated button text using knockout

I am loading data to grid dynamically and I am having 'Add' button in every row.

btn = "<a id='btnRow' data-bind='click: function()
    { ClickAdd(\"" + rowObject.Id+ "\")}'>" +
    "<i ></i><span data-bind='text:$root.StrResources.BtnAdd'/></a>";

as shown above I am setting the text for button using data-bind

Now on clicking the button i want to change the text from 'Add' to 'Selected' I do have property in javascript object as

StrResources: {
    BtnView: ko.observable("View"),
    BtnAdd: ko.observable("Add"),
    BtnSelected: ko.observable("Selected"),
},

In java script object i do have method to perform add operation

empObject.ViewModel.ClickAdd = function (objectDN, objectName) {
    // here i want to write code to change the text.
};

How can i do it?

Upvotes: 2

Views: 8939

Answers (2)

Paul
Paul

Reputation: 1502

I see what you're trying, but I'm not sure that's the right way to do things. Your resources object contains some observables, but the point of observables is that when you change them your previously bound UI changes to reflect the changes in the observable. My confusion is that your resources should be static.

Then I see you're binding to those resources however your method of binding the button text is hard coded to use the StrResources.BtnAdd resource; and if you update that observable to 'Selected', then ALL the buttons bound to StrResources.BtnAdd will then change to have the text of 'Selected'.

What you really need is a way to specify text per button rather than have all buttons bound to one observable.

Reading between the lines of your question, I implemented a simple grid here that I think meets your requirements:

http://jsbin.com/finucabo/1/edit?html,js,output

The parts of interest are:

var model = {
    grid: {
        row: ko.observableArray(),

        selected: ko.observable()
    },

    buttonText: function (row) {
        return model.grid.selected() === row ? 'Selected' : 'Add';
    },

    buttonClick: function (row) {
        if (model.grid.selected() === row) {
            model.grid.selected(null);
        } else {
            model.grid.selected(row);
        }
    }
};

And the binding:

<!-- ko foreach: grid.row -->
<tr>
    <td data-bind="text: first"></td>
    <td data-bind="text: last"></td>
    <td data-bind="text: email"></td>
    <td>
        <button
            type="button"
            data-bind="click: $root.buttonClick, text: $root.buttonText($data)">                    
        </button>
    </td>
</tr>
<!-- /ko -->

Notice that clicking the button simply stores the current row into the model.grid.selected observable. This will cause buttonText to re-evaluate for the text binding.

Hope this is of some help to you.

EDIT:

With respect to being able to select multiple rows, you could just change selected into an observable array.

I've updated the jsbin here: http://jsbin.com/finucabo/2/edit

The changes are:

// Helper function added.
function arrayContains(anArray, aValue) {
    return ko.utils.arrayFirst(anArray(), function (v) {
        return v === aValue;
    }) !== null;
}

var model = {
    grid: {
        row: ko.observableArray(),

        // Now using an observable array.
        selected: ko.observableArray()
    },

    buttonText: function (row) {
        // Modify to use observable array.
        return arrayContains(model.grid.selected, row) ? 'Selected' : 'Add';
    },

    buttonClick: function (row) {
        // Modify to use observable array.
        if (arrayContains(model.grid.selected, row)) {
            model.grid.selected.remove(row);
        } else {
            model.grid.selected.push(row);
        }
    }
};

Upvotes: 2

Wayne Ellery
Wayne Ellery

Reputation: 7958

You would just bind the text to an observable:

<button data-bind="click: changeButtonText, text: buttonText"></button>

then in the click function, you would change the text:

var Row = function(row) {
    var self = this;

    self.buttonText = ko.observable('Add');

    self.changeButtonText = function() {
        self.buttonText('Selected');
    };
};

http://jsfiddle.net/Wk7dr/3/

Upvotes: 3

Related Questions