Anubis
Anubis

Reputation: 2624

KnockoutJS chain dependend properties

Does anyone have a working example of chain-dependend properties in a ViewModel? The code example will explain what I'm talking about:

<script type="text/javascript">
    var ViewModel = function () {
        this.SelectedPubCode = ko.observable('@Model.PubCode');
        this.SelectedVersionName = ko.observable('@Model.VersionName');
        this.PubCodes = ko.observable(@Model.PubCodes.ToJavascriptArray());
        this.VersionNames = ko.observable(@Model.VersionNames.ToJavascriptArray());

        this.LoadVersionNames = function(pubCode) {
            var self = this;
            $.ajax({
                type: "POST",
                url: '@Url.Action("LoadVersionNames")',
                data: "pubCode=" + pubCode,
                success: function(data) {
                    self.VersionNames(data);
                    // Trigger chain call (will call SelectedVersionName subscribtion).
                    self.SelectedVersionName('');
                }
            }); 
        };

        this.SelectedPubCode.subscribe(function(newPubCode) {
            // Accessing public variable to call model's method
            model.LoadVersionNames(newPubCode);
        });

        this.SelectedVersionName.subscribe(function(newValue) {
            // Another model's method can be called here.
            alert("Version Name has been changed to '" + newValue + "'");
        });
    };
    // Creating public variable to access it from inside of subscribtion action
    var model = new ViewModel();
    ko.applyBindings(model);
</script>

Please look at the this.SelectedPubCode.subscribe(function(newPubCode) call. I have to use global variable to make this working. Is there any other way to achieve the behaviour I want?

Upvotes: 0

Views: 717

Answers (1)

Artem Vyshniakov
Artem Vyshniakov

Reputation: 16465

Knockout team is recommended to use self variable in view model to store this pointer. In this case you can use self to call LoadVersionNames function instead of using global variable.

Your code should look as follow:

<script type="text/javascript">
    var ViewModel = function () {
        var self = this;
        self.SelectedPubCode = ko.observable('@Model.PubCode');
        self.SelectedVersionName = ko.observable('@Model.VersionName');
        self.PubCodes = ko.observable(@Model.PubCodes.ToJavascriptArray());
        self.VersionNames = ko.observable(@Model.VersionNames.ToJavascriptArray());

        self.LoadVersionNames = function(pubCode) {
            $.ajax({
                type: "POST",
                url: '@Url.Action("LoadVersionNames")',
                data: "pubCode=" + pubCode,
                success: function(data) {
                    self.VersionNames(data);
                    // Trigger chain call (will call SelectedVersionName subscribtion).
                    self.SelectedVersionName('');
                }
            }); 
        };

        self.SelectedPubCode.subscribe(function(newPubCode) {
            // Accessing public variable to call model's method
            self.LoadVersionNames(newPubCode);
        });

        self.SelectedVersionName.subscribe(function(newValue) {
            // Another model's method can be called here.
            alert("Version Name has been changed to '" + newValue + "'");
        });
    };
    // Creating public variable to access it from inside of subscribtion action
    var model = new ViewModel();
    ko.applyBindings(model);
</script>

Upvotes: 2

Related Questions