Solved

Accessing observable variable before and after setting a value is not working

Posted on 2016-09-25
4
47 Views
Last Modified: 2016-09-25
I have 2 variables declared as mtn and atn whose values get populated based on the API ajax response.

Now, I am assigning mtn and atn variables with a value returned from API response and in my case since mtn is coming as null whereas atn is having a 10 digit number. So I am assigning atn1, atn2, atn3 with substring of atn whereas mtn1, mtn2 and mtn3 is untouched as you can see from below code snippet.



var ViewModel = {
mtn: null,
atn: null,
mtn1: ko.observable(null),
mtn2: ko.observable(null),
mtn3: ko.observable(null),
atn1: ko.observable(null),
atn2: ko.observable(null),
atn3: ko.observable(null)
}
// Ajax API call happens and assigns ViewModel.mtn and ViewModel.atn
if (ViewModel.mtn != null && ViewModel.mtn.length == 10) { //This condition is not true because ViewModel.mtn is coming as null in case and so mtn1, mtn2 and mtn3 observables are untouched
ViewModel.mtn1 = ViewModel.mtn.substring(0, 3);
ViewModel.mtn2 = ViewModel.mtn.substring(3, 6);
ViewModel.mtn3 = ViewModel.mtn.substring(6, 10);
}
if (ViewModel.atn != null && ViewModel.atn.length == 10) {
ViewModel.atn1 = ViewModel.atn.substring(0, 3);
ViewModel.atn2 = ViewModel.atn.substring(3, 6);
ViewModel.atn3 = ViewModel.atn.substring(6, 10);
}
ko.applyBindings(ViewModel);

// Click event happens from View and Business logic UI validations take place below
processClick: function() {
     .var strmtn = ViewModel.mtn1 + ViewModel.mtn2 + ViewModel.mtn3; // This is not working and throwing error and only ViewModel.mtn1() is working
      var stratn = ViewModel.atn1 + ViewModel.atn2 + ViewModel.atn3; // This is working fine but ViewModel.atn1() is not working.

Open in new window


I believe the reason for the method of accessing atn1 as ViewModel.atn1 is working whereas method of accessing mtn1 as ViewModel.mtn1 is not working is because of re-assignment of observable for atn1 whereas mtn1 is not touched.



So how do I know which method of access to invoke an observable value since I don't know if my observables were touched or not ? :(
0
Comment
Question by:gopikrish
  • 2
4 Comments
 
LVL 32

Accepted Solution

by:
ste5an earned 500 total points
ID: 41814734
First of all: Please post a concise and complete example.

Then you need to access the observable values by using the () syntax. And why don't you use a computed observable for your sums?

E.g.
<!DOCTYPE html>
<html>
    <head>
        <script src="jquery-3.1.1.min.js"></script>
        <script src="knockout-3.4.0.js"></script>
        <script>
            $( document ).ready(function() {
                ViewModelContainer = new ViewModel();
                ko.applyBindings(ViewModelContainer);
            });
        </script>
        <script>
            var ViewModelContainer;
            function ViewModel() {
                var self = this;
                self.mtn = ko.observable(null);
                self.mtn1 = ko.observable(null);
                self.mtn2 = ko.observable(null);
                self.mtn3 = ko.observable(null);
                self.strmtn = ko.computed(function() {
                    return (
                        self.mtn() === null 
                            ? 'n/a' 
                            : self.mtn1() + '-' + self.mtn2() + '-' + self.mtn3()
                    );
                });
                self.simulateAjax = function() {
                    self.mtn('1234567890');
                    if (self.mtn() !== null && self.mtn().length === 10) {
                        self.mtn1(self.mtn().substring(0, 3));
                        self.mtn2(self.mtn().substring(3, 6));
                        self.mtn3(self.mtn().substring(6, 10));
                    }
                };
            }
        </script>
    </head>
    <body>
        <button data-bind="click: simulateAjax">AJAX</button>
        <div data-bind="text: mtn"></div>
        <div data-bind="text: mtn1"></div>
        <div data-bind="text: mtn2"></div>
        <div data-bind="text: mtn3"></div>
        <div data-bind="text: strmtn"></div>
    </body>
</html>

Open in new window


And maybe even your mtnX can be computed:
function ViewModel() {
    var self = this;
    self.mtn = ko.observable(null);
    self.mtnIsValid = function() {
        return (self.mtn() !== null && self.mtn().length === 10);
    }
    self.mtn1 = ko.computed(function() {
        return (self.mtnIsValid() ? self.mtn().substring(0, 3) : null);
    });
    self.mtn2 = ko.computed(function() {
        return (self.mtnIsValid() ? self.mtn().substring(3, 6) : null);
    });
    self.mtn3 = ko.computed(function() {
        return (self.mtnIsValid() ? self.mtn().substring(6, 10) : null);
    });
    self.strmtn = ko.computed(function() {
        return (self.mtnIsValid() ? self.mtn1() + '-' + self.mtn2() + '-' + self.mtn3(): 'n/a');
    });
    self.simulateAjax = function() {
        self.mtn('1234567890');
    };
}

Open in new window

0
 
LVL 82

Expert Comment

by:leakim971
ID: 41814764
ajax call are most of time asynchronous
looking the code you posted, it look like you don't run the code starting line 12 after the end of the ajax call. you run it just after doing the ajax call.
you must run this code in the callback of the ajax call
0
 
LVL 32

Expert Comment

by:ste5an
ID: 41814796
btw, when the AJAX call is your problem then it depends on your returned data by this call. When it for example return { "mtn": "1234567890", "atn": "abcdefghij" }, then you can use e.g jQuery.

$.getJSON("/some/url", function(data) { 
        ViewModelContainer.mtn(data.mtn);
})

Open in new window


in
<!DOCTYPE html>
<html>
    <head>
        <script src="jquery-3.1.1.min.js"></script>
        <script src="knockout-3.4.0.js"></script>
        <script>
            $( document ).ready(function() {
                ViewModelContainer = new ViewModel();
                ko.applyBindings(ViewModelContainer);
                $.getJSON("/some/url", function(data) {
                    ViewModelContainer.mtn(data.mtn);
                })
                .done(function() {
                    console.log("success: got data from AJAX.");
                    console.log(ko.toJSON(data, null, 2));
                })
                .fail(function() {
                    console.log("error: AJAX call failed.");
                    console.log("error: running with simulated data.");
                    ViewModelContainer.mtn('SIMULATED.');
                });
            });
        </script>
        <script>
            var ViewModelContainer;
            function ViewModel() {
                var self = this;
                self.mtn = ko.observable(null);
                self.mtnIsValid = function() {
                    return (self.mtn() !== null && self.mtn().length === 10);
                }
                self.mtn1 = ko.computed(function() {
                    return (self.mtnIsValid() ? self.mtn().substring(0, 3) : null);
                });
                self.mtn2 = ko.computed(function() {
                    return (self.mtnIsValid() ? self.mtn().substring(3, 6) : null);
                });
                self.mtn3 = ko.computed(function() {
                    return (self.mtnIsValid() ? self.mtn().substring(6, 10) : null);
                });
                self.strmtn = ko.computed(function() {
                    return (self.mtnIsValid() ? self.mtn1() + '-' + self.mtn2() + '-' + self.mtn3(): 'n/a');
                });
            }
        </script>
    </head>
    <body>
        <div data-bind="text: mtn"></div>
        <div data-bind="text: mtn1"></div>
        <div data-bind="text: mtn2"></div>
        <div data-bind="text: mtn3"></div>
        <div data-bind="text: strmtn"></div>
    </body>
</html>

Open in new window

0
 

Author Closing Comment

by:gopikrish
ID: 41814802
Thanks !
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

WHY MVC is the future technology... As many of you know, MVC is Model,View,Controller pattern. Model View Controller pattern was invented in a Smalltalk context at Xerox in late 1970s. Why is this buzz about MVC: --------------------------- …
In Part 1 (http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/A_7849-Hex-Maze.html) we covered the hexagonal maze basics -- how the cells are represented in a JavaScript array and how the maze is displayed.  In this part, we'…
The purpose of this video is to demonstrate how to set up the WordPress backend so that each page automatically generates a Mailchimp signup form in the sidebar. This will be demonstrated using a Windows 8 PC. Tools Used are Photoshop, Awesome…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now