Modifying view after rendering finishes


#1

Hello,

I’ve been using CanJS for a little while and I keep running into the same problem. Say I have a model and I render a view based on that model. Now I want to change the dom elements that were generated while rendering the view somehow (say I have a jQuery plugin that I want to apply to some rendered elements). The problem is that these elements won’t exist yet, they will exist once canJS has rendered them completely.

Here’s an example of what I mean: https://jsfiddle.net/z6q5efwu/

In the example, I render the list of inputs, and I’d like to focus the last one, but I can’t because it hasn’t actually been rendered yet. I’ve looked into some possible solutions to this:

  1. Use the Async Loading
    docs/can.view.html#section_AsynchronousLoading
    This is the most obvious solution in the demo I linked, but this doesn’t work in all cases. If I want to do the same thing from a change listener on a model, for instance, I run into the same problem but can’t solve it with this.

  2. Autorender
    docs/can%7Cview%7Cautorender.html
    This seems to be more geared towards doing one action after all templates have finished rendering. It’s not exactly what I’m looking for and I had some trouble getting it to work.

  3. can.events.inserted
    docs/can.events.inserted.html
    I had some trouble getting this to work as well, from what I gather this will be fired when the element getting rendered is actually rendered on the DOM? This could be what I’m looking for but I couldn’t get a working example going using the documentation.

Hopefully I’ve explained my goal clearly, if not I can elaborate. I feel like I’m missing something, is there a right way to accomplish what I’m looking for?

Thanks


#2

Hi! First off, have you looked into can.Component? It makes this sort of thing easier as there’s more of a convention.

In your example it’s hard to answer because rendering is not finished in your render function (by the way, conventionally we did rendering in the Control’s init). Rendering is only complete after you’ve added the last item.

I think it’s probably better for the Control to fetch it’s own items to add to the list, this way you will know when it is complete and that you can now focus.


#3

as Matthew says, can.Component is the better way.
i made an example how i can looks like:

but even better is that:

hope thats help you.

feel free to comment


#4

I also want to know when a stache template is done rendering, not only the first time when it is inserted.

For example when an attribute of the viewmodel changes, the template re-renders the interface, I would like to know when this event is ready.

Here is an example:

The activeForm attribute is updated when you click the button, the makes the interface re-render just as I wanted but I have no idea when it’s done rendering, so I can set the focus to an input for example.

I already learned you can also attach a, inserted event on a tag, but this also gets triggered once, and stache re-uses the element.
<h1 ($inserted)="elinserted(@element)">{{label}}</h1>

@cherif_b suggested to remove the component and insert it again, but this feels so wrong in the CanJS live-binding philosophy.
Here is an example : http://jsbin.com/tuciqivuxi/1/edit?html,js,output

Any suggestions/thoughts?


#5

I worked around my issue by using @pYr0x technique of adding a focus attribute to my input components.

I haven’t really found another solution such as rendered event.