2

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

Ashwin
  • 262
  • 2
  • 5
  • 13
  • So "object" is a function? A function that when called returns an object? If not, then `object().property` is incorrect. – Pointy May 04 '13 at 14:49
  • Both version should and does work the same: http://jsfiddle.net/sAkb4/. So you have your problem elsewhere... you should try to reproduce your problem in a jsfiddle... – nemesv May 04 '13 at 15:07
  • Yes, my issue is that when the dom loads the list not available shows momentarily even though the list is available since the object are calculated at the end.. – Ashwin May 04 '13 at 15:34
  • Perhaps you could CSS `display: none;` the `span` or `p` tag to make it not visible on the initial load, then use the visible binding? You should be able to use `if: object && !object().property` as well and eliminate one of your span tags (unless they are there for a reason). – kendaleiv May 04 '13 at 19:02

3 Answers3

2

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 -->
  • With the solution it does the same thing if I am not wrong.. Initially a template is displayed then it changes... But my problem is that the property is an array and it takes little time to populate it.. When the Object is available it displays the message.. – Ashwin May 05 '13 at 01:55
  • As shown by the fiddle, this solution will show nothing until Object is created, then the "not available markup" until Object has the property set to true, then the "available markup". – Ricardo Medeiros Penna May 05 '13 at 13:52
  • I think the problem might reside in the condition to show each template not being very clear. Could you try to clarify when each template should be visible? – Ricardo Medeiros Penna May 05 '13 at 14:00
0

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.

CodeThug
  • 3,054
  • 1
  • 21
  • 17
  • How are you passing the value if the ko/ajax is completed ? Because the object exists and it takes a little while for it populate the property which is an array... So thats the reason it is displaying for a moment.. I want to know if the all the operation is done, then display this message.. – Ashwin May 05 '13 at 01:59
  • I'm getting a little confused... can you show what object and property are so that we can have a little better idea of what these objects look like? – CodeThug May 06 '13 at 01:50
  • Hey, This is the explanation.. The object contains an array, the array items are populated by ajax call.. Now, when the ajax call returns items display the list of items, if none is returned say "nothing returned" .... But since when loading the ajax call still happening the DOM displaying "nothing returned" for a while... How do I make the DOM wait for the ajax call to finish and then display.. – Ashwin May 06 '13 at 14:35
0

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);
Anders
  • 17,306
  • 10
  • 76
  • 144