Chun ping Wang
Chun ping Wang

Reputation: 3929

Knockout: Writable computable observable update each other

I have a case where I need to do the following.

Selecting employment type will trigger default monthly salary and yearly salary.

UI:

    <select id="empType" data-bind="value: $data.empType, valueUpdate: 'afterKeyDown'">
    <option value="DEFAULT">default</option>
    <option value="GOOD"> Good</option>
</select>
<input type="text" id="monthlySalary" data-bind="value: $data.monthlySalary, valueUpdate: 'afterKeyDown'"/>
<input type="text" id="yearlySalary" data-bind="value: $data.yearlySalary, valueUpdate: 'afterKeyDown'"/>

My Model:

    function formatCurrency(z) {
    "use strict";
    var s, x, c, i, v;
    if(z === ""){return "";}
    x="0"+z.toString().replace(/\$|\,/g,'');
    if(isNaN(x)){z="";return "";}
    x=parseFloat(x);
    s=(x === (x=Math.abs(x)));
    x=Math.floor(x*100+0.50000000001);
    c=x%100;
    x=Math.floor(x/100).toString();
    if(c<10) {
        c="0"+c;
    }
    for (i=0; i<Math.floor((x.length-(1+i))/3); i += 1) {
        x=x.substring(0,x.length-(4*i+3))+','+x.substring(x.length-(4*i+3));
    }
    z=v=(((s)?'':'-')+'$'+x+'.'+c);
    return v;
}

function unformatCurrency(x) {
    "use strict";
    var y = x.toString().replace(/\$|\,|\)/g,''), temp;
    if(y.indexOf("(") !== -1){ // for negative numbers which are displayed in ( )
        temp = y.replace("(", "-");
        y = temp;
    }
    return y;
}

function EmploymentModel() {
    var self = this;
    self.empType = ko.observable("");
    self.monthlySalary = ko.computed(
   {
    read:function() {
        if (self.empType() === "DEFAULT") {
            return formatCurrency(1000);
        } else {
            return formatCurrency(2500);
        }
    },
    write: function(amount) {
        // i need to do something like this. 
        // this.value = formatCurrency(this.value) in javascript. 
        // updated yearly salary which is monthly * 12. 
    },
    deferEvaluation: true
   },
   this);
   self.yearlySalary=ko.computed(
   {
    read:function() {
        return formatCurrency(unformatCurrency(self.monthlySalary()) * 12);
    },
    write: function(amount) {
        // i need to do something like this. 
        // this.value = formatCurrency(this.value) in javascript. 
        // updated monthly salary by dividing by 12. 
    },
    deferEvaluation: true
   },
   this);
}

var empModel = new EmploymentModel();
ko.applyBindings(empModel);

So I got the first part working which is changing employment type would generate default value.

Now I need to have it so that whenever monthly salary is enter than it will auto update yearly salary and vice Versa.

  1. User select default, than monthly salary should be $1000 , which would make yearly salary $12000.

  2. User enters 500 for monthly salary, than it becomes $500 (formatted) and also updates yearly salary to $6000.

  3. User enters 120000 for yearly salary, than it becomes $120000 (formatted) and also updates monthly salary to $10000.

Any advice or help?

Here is the fiddle (that does not solve case 2 and 3).

Upvotes: 0

Views: 387

Answers (1)

Akhlesh
Akhlesh

Reputation: 2399

you should have base observable on which you want computed so i have updated you fiddle.

function EmploymentModel() {
 var self = this;
 self.empType = ko.observable("DEFAULT");
 self.monthly = ko.observable(1000);
 self.yearly = ko.observable(12000);
 self.monthlySalary = ko.computed({
    read: function () {
        if (self.empType() === "DEFAULT") {
            self.monthly(1000);
            return formatCurrency(self.monthly());
        } else if (self.empType() === "GOOD") {
            self.monthly(2500);
            return formatCurrency(self.monthly());
        } else {
            return formatCurrency(self.monthly());
        }
    },
    write: function (amount) {
        // i need to do something like this.
        self.empType(null);
        self.yearly(unformatCurrency(amount) * 12);
        self.monthly(unformatCurrency(amount)); // in javascript. 
        // updated yearly salary which is monthly * 12. 
    },
    deferEvaluation: true
},
this);
self.yearlySalary = ko.computed({
    read: function () {
        if (self.empType() === "DEFAULT") {
            self.yearly(12000);
            return formatCurrency(self.yearly());
        } else if (self.empType() === "GOOD") {
            self.yearly(30000);
            return formatCurrency(self.yearly());
        } else {
            return formatCurrency(self.yearly());
        }
    },
    write: function (amount) {
        // i need to do something like this. 
        self.empType(null);
        self.yearly(unformatCurrency(amount));
        self.monthly(unformatCurrency(amount) / 12);
        // updated monthly salary by dividing by 12. 
    }
 },
 this);
}

Fiddle Demo

Upvotes: 1

Related Questions