how to use if else in knockout - javascript

How to perform following operation in knockout
<div id="mainlist" data-bind="foreach: PageData.messages">
<article class="comment_chain" id="_parentpost" >
<div class="post_holder">
<!-- ko if: ObjectId === 4 -->
DO SOMETHING
<!-- /ko -->
</div>
here if condetion is no getting called properly . wat may b the reason for this.

Is ObjectId an observable? If so when you use an observable in an expression you have to remember that it is really a function and you need to use the () form to get the underlying value. Try this:
<!-- ko if: ObjectId() === 4 -->

Related

knockout "X is not defined" error

I have a knockout model and am getting an error that I do not understand.
Here is the offending section of code:
<!-- ko with: SearchModel -->
...
<img class="search-img" data-bind="visible: searching" src="#Url.Content("~/Static/Hypercube_Large_Light_Transparent.gif")" height="30" />
<img id="searchIcon" class="search-img" data-bind="visible: !searching()" src="#Url.Content("~/Static/search_icon.png")" height="30" />
...
<!-- /ko -->
In SearchModel.js:
...
this.searching = ko.observable(false);
...
I get an error on the SECOND reference to searching. The first one resolves just fine, and there are no other errors. Weird thing, the code actually WORKS, so whenever I change the searching variable to true, the second image goes away and the first one appears, then when I change it back to false, the first goes away and the second appears.
Uncaught ReferenceError: Unable to parse bindings.
Bindings value: visible: !searching()
Message: searching is not defined
I suspect that you need to check for the existence of SearchModel prior to the with binding.
Something like:
<!-- ko if: SearchModel() -->
Or more specific:
<!-- ko if: SearchModel() !== 'undefined' && SearchModel() !== null -->
You could also, depending on your view model hierarchy, create a ko.pureComputed to check the existence of the SearchModel and in the HTML use code like:
<!-- ko if: SomePureComputed -->

How to run functions in afterRender in knockout binding?

I need to add a datepicker to a textbox input, whose visibility is controlled by a knockoutjs binding.
<!-- ko if: hasWorked -->
<div class="form-group">
<input id="StartDate" name="StartDate" type="text" />
</div>
<!-- /ko -->
My guess is:
<!-- ko if: hasWorked, afterRender:initDatepicker -->
But it never worked.
What is the correct way to show a textbox and then run a function to process it?
afterRender is only available to foreach and template.
Luckily, we can do containerless template.
So the solution:
<!-- ko template: {if: hasWorked,afterRender:initDatepicker} -->
...
<!-- /ko -->
References:
Containerless template The solution provided by Maksym
Kozlenko. Not the selected answer.
The use of afterRender in template, see the knockout official documentation on template, (scroll down to Note 4).

Knockout if binding inside a template does not show now matter what value the observable holds?

I have a simple template with an if binding inside it:
<script type="text/html" id="addPersonTemplate">
<tr>
...
<td class="large-7" data-bind="text: addPersonUsername"><span class="noSpecificChecks" data-bind="if: addPersonUsername() == false">No username added</span></td>
...
</tr>
</script>
Basically, a person has an option to enter a username. When they click 'add' somewhere else in the document, the template is outputted, however, no matter what I try:
I cannot get if: addPersonUsername() == false to evaluate correctly.
If the expression evaluates to true (there is no username) I want to output "No username added". Yet, if I enter no username, the addPersonUsername() variable is undefined (checked via console.log) and yet this text is not outputted.
Is there any particular reason for this? Is the if binding only evaluated at HTML page load, not at template addition? I can't see any indication it is...
Knockout observables are functions so you need to get their value with calling them without any argument (e.g.: addPersonUsername()) when they are used in any expression like inside an if binding:
<span class="noSpecificChecks" data-bind="if: addPersonUsername() == false">
Beside that your HTML is structured incorrectly. When you apply the text binding on the td it replaces the whole content of the td so also your span with the if.
So you need to apply the text something else inside the td like on a span (or use the virtual element syntax if you don't need the span):
<td class="large-7" >
<!-- ko if: addPersonUsername -->
<span data-bind="text: addPersonUsername"></span>
<!-- /ko -->
<span class="noSpecificChecks" data-bind="if: addPersonUsername() == false">No username added
</span>
</td>
Demo JSFiddle.

Accessing current Knockout binding context

Take a look at the following code, with a focus on the embedded script:
<tr>
<!-- ko foreach: { data: foos, as: 'f' } -->
<td>
<!-- ko if: f.someCondition() -->
<input id='picker' />
<script type="text/javascript">
$("#picker").kendoDatePicker({
value: new Date(),
change: f.changeFunction }); <!---- note this line -->
</script>
<!-- /ko -->
</td>
<!-- /ko -->
</tr>
See f.changeFunction? I'm getting a JavaScript error that f is not defined. How do I access the current binding context so I can attach the Kendo change handler to my current foo? I've tried using a few of the binding context variables but they aren't accessible outside of the binding expressions. If I can't access the binding context in the embedded script, is there a workaround?
Is there a reason you aren't using the kendo-knockout bindings?
http://rniemeyer.github.io/knockout-kendo/web/DatePicker.html

Knockout js - && in if condition and containerless binding

I am displaying a list of items and if the items are not available I have to display a default message. Now, I have to check whether the object has been created and then check the object has the list in it.
So now, I am doing the below and it works it creates unnecessary dom elements. But, when I do the same with the containerless binding it doesn't seem to work and also is there an && syntax for if in KO
<span data-bind="if: object">
<span data-bind="if: !object().property">
<p> The list is not available </p>
</span>
</span> // Works
<!-- ko if: object -->
<!-- ko if: !object().property -->
<p> The list is not available </p>
<!-- /ko -->
<!-- /ko --> // Doesn't work
Thanks
As mentioned by CodeThug, using the solutions you provided would display the message until ko.applyBindings have finished. A more verbose solution, but that would avoid the problem without relying on CSS, is to use dynamic templates as shown in the following jsfiddle:
http://jsfiddle.net/sAkb4/1/
This will create the valid markup inside the virtual element only when the ko.applyBindings is done.
<!-- ko template: { name: dinamycList } -->
<!-- /ko -->
<script type="text/html" id="empty-template">
... list is NOT available markup ...
</script>
<script type="text/html" id="list-template">
... list is available markup ...
</script>
Being dinamycList a function that returns the name of the template according to the verifications you want for a valid list.
EDIT:
Reading thru your last comment made me think if the behaviour that you want is to display the "not avaiable template" only after calculating the list and the property is false, if thats the case, the following fiddle will fix the last one to provide the right condition.
http://jsfiddle.net/sAkb4/3/
The "if" condition in template will handle the moment after knockout is ready, but before the list is. If the condition gets too messy, i would advise to put it inside a ko.computed for a clear markup.
<!-- ko template: { name: dinamycList, if: object() !== undefined && object().property !== undefined } -->
<!-- /ko -->
As you have seen, the element exists in the DOM, and it won't be removed until the ko.applyBindings call is finished. Thus the momentary display of this message.
I'd try hiding the entire section of the DOM and show a loading indicator instead. When ko/ajax is done, the loading indicator can then be removed and the markup you care about displayed.
Alternately, you could see if your page is taking a while to load and try to improve the load time of the page. The chrome profiling tools can help with this.
THis is very easy with my Convention over configuration lib
http://jsfiddle.net/VVb4P/
Just this and the lib will do the templatating for you
this.items.subscribe(function(items) {
if(items.length === 0) {
this.items.push(new MyApp.EmptyViewModel());
}
}, this);

Categories