JQuery UI Accordion/Sortable, ng:repeat, binding

2,766 views
Skip to first unread message

Robert B. Weeks

unread,
Dec 14, 2011, 6:44:36 PM12/14/11
to ang...@googlegroups.com
Hello all -

I have been trying to figure out how to utilize either a directive or a widget to take a list/array of elements, and create an accordion element out of it, and have it be sorted, binding the sort to the original array.

I saw some of the previous messages about the JQuery UI Slider and the bind - and started going down that path - but am having quite a few issues.

I tried to do this via directives and widgets so that I have access to the scope and can try to update the array of elements upon sort - but I am having a hard time with the order/timing of this it seems.

When I assign a directive to the element to be rendered as an accordion - it never seems to do so upon load. Odd thing is - it is still sortable. If I do a destroy and then a new accordion on the element at some later time (as seen by hitting the 'Add Type' link) - the whole thing will render. Almost like I need to call this when the load is done this was as well.

jsfiddle: http://jsfiddle.net/vaiism/uNuCe/

This is broken up into 3 section:

* Not using ng:repeat with directive
This is manual elements not build via ng:repeat.

* Using ng:repeat with directive
This is using the ng:repeat to build the elements to be rendered. Is there an event that is fired off once ng:repeat is complete? I can maybe try to accordion the list then.

* Using ng:repeat rendered on page load, not directive
Showing how the original does render on the page load with the ng:repeat.


I still need to bind the order to the array when this is figured out, but any thoughts would be appreciated.

Thanks!

--
Robert B. Weeks


Vojta Jina

unread,
Dec 16, 2011, 3:37:43 AM12/16/11
to ang...@googlegroups.com
Hi Robert,

accordion directive without ng:repeat (1st example)
What is the issue there ? I think it works fine. This should be easy use case, when the content is static, just create accordion inside linking function

Doing stuff after ng:repeat renders
With current compiler, you don't know, when children were "linked", so this is not easy. You can use setTimeout() to do it after ng:repeat renders, but it's not nice, I know.
This should be possible with new compiler, which should be released pretty soon.

accordion + ng:repeat
Problem of jq accordion is that it doesn't have any "update" method, as far as I know. So when you update the DOM by ng:repeat for example, you would have to destroy the accordion and create again, which is not great...

sortable + ng:repeat
Again, this is not easy :-D ng:repeat works only one way. You change the model (js object/array) and ng:repeat update DOM.
I don't know details about sortable implementation, but you might try to change it, to update given model, instead of DOM. ng:repeat would update DOM then...

Misko might help you more,

V.

Robert B. Weeks

unread,
Dec 16, 2011, 8:58:31 AM12/16/11
to ang...@googlegroups.com
Hello Vojta -

>
> accordion directive without ng:repeat (1st example)
> What is the issue there ? I think it works fine. This should be easy use case, when the content is static, just create accordion inside linking function

Right - this was showing one working without the ng:repeat - like a base of what was wanted.

> Doing stuff after ng:repeat renders
> With current compiler, you don't know, when children were "linked", so this is not easy. You can use setTimeout() to do it after ng:repeat renders, but it's not nice, I know.
> This should be possible with new compiler, which should be released pretty soon.
>
> accordion + ng:repeat
> Problem of jq accordion is that it doesn't have any "update" method, as far as I know. So when you update the DOM by ng:repeat for example, you would have to destroy the accordion and create again, which is not great...

Right - I have been using a destroy/rebuild of the element.

I have this actually working mostly except for one big issue - I cannot get the original load to render right - it is a timing issue. I was going to create a widget out of this - but reading back in the discussions seems those might be going to be basically all directives?

So I am trying to tie this into a directive so I have access to the model/controller in the renderings - that registers itself as a list element once it is hit - so I know which element to run through the accordion.

I need to find an event that fires after ng:repeat is done - so I know the rendered view model is complete before running the original accordion/sort method. Once I hit the 'add' button and call the render directly - it all works (for the most part).


Is there an event that is fired after ng:repeat renders??

> sortable + ng:repeat
> Again, this is not easy :-D ng:repeat works only one way. You change the model (js object/array) and ng:repeat update DOM.
> I don't know details about sortable implementation, but you might try to change it, to update given model, instead of DOM. ng:repeat would update DOM then...

Here - they do have events that will give a serialization of the order via id's of the elements - so for now am actually taking that and re-ordering the array in the model manually until I get it figured out smoother.

Something like:

<div ng:repeat="messageType in interfaceSettings.messageTypes" id="{{$index}}">

So I can get an array representation of the current order via the $index id and then adjust the model in the controller. Not ideal yet - but getting there. I think once I get a way to know when ng:repeat is complete - this will work well.

>

Thanks a lot for the response! Huge angular fan.

--
Robert B. Weeks


Miško Hevery

unread,
Dec 16, 2011, 2:03:21 PM12/16/11
to ang...@googlegroups.com
Hi Robert,

What you are doing is tricky, but let me try to help you out, but it will probably take few emails.

I think the best approach is to use custom ng:repeat. 

The problem with ng:repeat, is that it will make new DOM, but the jQUI wants to add tabs programmatically not by changing DOM, so it is unlikely to work. But just for your info you can know when you are created by adding additional directive inside the ng:repeat, and the link function of the directive will get called on each element creation. You can then register a element.bind('$destroy', fn(){}) on the element to know when the DOM element is removed.

Here is what I would do (study ng:repeat to understand what I am saying)

<accordion source="some.array">
  Code inside HTML
</accordion>


1) compiled the contents of the accordion into the template
2) replace accordion with jQUI accordion with no panels
3) watch some.array, and see if an item has been added/removed into the expression.
4) when new item is inserted int an array then programmatically add item into accordion and add the clone of the template into the panel
5) when removed then do the reverse.

-- Misko

Robert B. Weeks

unread,
Dec 20, 2011, 12:34:13 PM12/20/11
to ang...@googlegroups.com
Hey Misko -

Thanks for the reply.

Above is what I needed to do. sigh. :|

I was not able to get the above done with what I was working with for this go around - but am working on it now to make a little cleaner.

I ended up doing some manual stuff to get this working the way it is now (have to release library for other dev's to use). I used an example I saw on the example angular fiddles to determine when the rendering was done on a component, and used that to set off the refreshing, etc. - as well as used the outcome of the sorted outcome (based on the 'id's) to update the array.

One of the things I was having issue with was updating the main model after that sorting. I ended up using $apply(expression + '=' + object) basically to update it - but don't like that too much.

Thanks again for the response - I am going to try to work the above in to a more usable component.

--
Robert B. Weeks


jinesh...@gmail.com

unread,
Sep 12, 2012, 5:35:53 PM9/12/12
to ang...@googlegroups.com
Hi Misko,

I am new to AnugularJs so have little hard time understanding this solution. I have a similar problem at hand where I want to decorate a table with JQuery Paginator widget once that table is rendered by ng-repeat. The problem is I am not sure when ng-repeat completes adding rows to the table and I have to call Paginator () once it has done rendering and table has all the rows.

Thanks, for your help in advance. You can email me code samples at jinesh...@gmail.com

Jinesh
Reply all
Reply to author
Forward
0 new messages