Reputation: 1516
I need to bind a <p>
tag to a value in my view-model.
Now normally this is not the issue, but in this case, the value is separated into multiple fields within the model, because it is an address.
So I have the "streetName" and "HouseNumber" as separate fields, but they both need to be shown in the HTML as a part of this
tag.
According to knockout.js's official documentation:
"The binding value can be a single value, variable, or literal or almost any valid JavaScript expression."
Now I notice the "almost" there, so I am reserved, but a simple string concatenation should be considered a "simple enough operation" yes? I need to bind the value of my <p>
tag to the values of two string fields within the model, what syntax would I use since the one I am trying is not working:
<p data-bind="text: dataBind1 + dataBind2"></p>
On a sidenote dataBind1 and dataBind2 are not really that simple, it is a nested function call, yadda, yadda, yadda, though they work perfectly fine when separated, I cannot, for the death of me get them to work when I want them "together" in a single element. Real bind values are:
<p data-bind="text: getModelData(processID).Property()[0].Street + getModelData(processID).Property()[0].HouseNumber"></p>
The view model itself is a JavaScript object (var viewModel
) which has certain methods, such as getModelData(ID), updateModelData(ID) and such. The ID being passed here is a "unique controller identifier" for the controllers of different parts of the page. There is some 1:1 vs 1:M mummbo jumbo here, but it is not relevant. The var viewModel
receives the information from an AJAX call and dynamically update's itself with additional properties, based on which controllers are jammed into the page. So it would have the "uniqueID" properties which are in fact, the knockout's view models.
This way all the view models are kept under the 'interface' of a single object. Something like this:
var viewModel = {
uniqueID: object, //knockout.js viewModel of Controller1
uniqueID2: object, //knockout.js viewModel of Controller2
getModelData(processID): function(){
//does stuff
}
}
So in this case accessing the getModelData(ID).Property()[0].Street
would be pretty much the same as accessing Property()[0].Street
in a regular non-deep-nested model or whatever you want to call it. And the structure of the knockout object itself is somewhat similar to:
{
Property: [
{
Street: "someStreet1"
HouseNumber: "someNumber1"
},
{
Street: "someStreet2"
HouseNumber: "someNumber2"
},
{
Street: "someStreet3"
HouseNumber: "someNumber3"
},
]
}
Upvotes: 0
Views: 1843
Reputation: 3634
I don't see how you have your View Model but here is what you can do.
var MainViewModel = function (){
var self = this;
self.Street = ko.observable(getModelData(processID).Property()[0].Street);
self.HouseNum = ko.observable(getModelData(processID).Property()[0].HouseNumber);
self.FullAddress= ko.computed(function () {
return self.Street() + ", " + self.HouseNum();
});
}
HTML
<p data-bind="text: FullAddress"></p>
Upvotes: 0
Reputation: 3175
You have to send a value, function (that returns a value), or an expression.
Example:
<p data-bind="text: (dataBind1() + dataBind2())"></p>
This SHOULD cause the evaluation to re-run on an observable update. I only know of a few cases that it will not.
Additionally you can use a computed value which guarantees the observable updates will re-compute the value. This also keeps logic out of the markup and is better for the newer browser security policies. See @Matt.kaaj's answer for that solution.
Finally you can use child elements like a span
which will not affect the markup and will be the most semantically correct.
<p><span data-bind="text: dataBind1"></span> <span data-bind="text: dataBind2"></span></p>
Upvotes: 3