2

I understand the basic features of Angular Controllers and Directives but I am struggling to see how I can best apply them to wrap the Dynatree tree widget that we use.

The issue is that Dynatree normally has its own means of retrieving data via ajax and populating itself - and normally you do this by calling its "appendAjax" method to append data to a particular tree node - i.e its all one operation.

I know that I could separate the call to the Ajax method and place this in the Controller storing the result of the ajax call in my own tree object - then I could watch for changes to that treeobject in my directive and then update the Dynatree widget manually. But the tree data I am dealing with is large and complex and it seems rather inefficient to have to maintain my own tree structure in the controller when dynatree already has its own tree structure.

My feeling is that in this case I really don't need a controller and instead I could just wrap up the Dynatree inside a directive and essentially keep using it the way I have always used it but this doesn't seem to work - and this is probably where my lack Angular knowledge about Directives occurs. So I have a few questions:

1] Is it considered bad practice to have any kind of ajax call inside a directive?

2] If so, how should I wrap this 3rd party control that likes to do things a certain way?Do I really need maintain my own duplicate tree structure in my Controller?

3] If it is deemed ok to make Ajax calls in a Directive how do I ensure the ajax method runs in the Directive? (I'm assuming this is the cause of my problems)

Dud
  • 361
  • 1
  • 3
  • 6
  • Does the rest of your application need to interact with the data in the tree? "essentially keep using it the way I have always used it but this doesn't seem to work" -- what doesn't work? – Mark Rajcok Mar 27 '13 at 02:37
  • What I meant was that if I keep the ajax call used by the Dynatree in the Directive no data is retrieved - even though its the exact same Javascript that I previously used successfully when it wasn't in a Directive. I think this is just down to my lack of understanding about how directives get compiled and linked. – Dud Mar 27 '13 at 09:07

3 Answers3

2

If its any help, here's a directive we're using in hawtio to wrap up jquery dynatree as an AngularJS directive.

Here's the source code (its in TypeScript but you should get the idea; its mostly JavaScript).

James Strachan
  • 9,168
  • 34
  • 31
0

1] Is it considered bad practice to have any kind of ajax call inside a directive?

I don't think so. If so Angular would not have a "controller" property where you can add arbitrary code, including Ajax calls. See my blog post here http://theocdcoder.com/guide-angularjs-directives-part/

2] If so, how should I wrap this 3rd party control that likes to do things a certain way? Do I really need maintain my own duplicate tree structure in my Controller?

I think the best option is to create a service wrapping your Ajax call, and call the service from the link method. Before that you need to initialize the Dynatree via JQuery/Javascript code in the link function, add event listeners to Dynatree events, which will live within your link function. Within these event listeners, you make more Ajax calls or modify the dom as necessary. You can also add $attr.$observe or $scope.$watch to listen to changes coming from outside. Use $scope.$broadcast to communicate to the parent controller or scope bindings to call methods to controller functions.

3] If it is deemed ok to make Ajax calls in a Directive how do I ensure the ajax method runs in the Directive? (I'm assuming this is the cause of my problems). See my blog post for an example.

You can post a JSFiddle for more clarity.

Ketan
  • 5,861
  • 3
  • 32
  • 39
  • I would like to add that putting any specific Ajax call in the directive will reduce the re-usability of the directive. – Ketan Mar 27 '13 at 03:15
  • Thanks for your answer. I am initialising the dynatree in my Directive's link function and trying to make ajax calls within dynatrees events. However what I haven't done is add my own Angular event listeners to listen to those dynatree events so I will look into that. – Dud Mar 27 '13 at 09:12
0

I faced a similar problem and got the same conclusion. My ajax call was returning after my directive had been loaded, hence the directive ended with no data at all. For this purpose I had 4 solutions out of which I believe the last one might be the best.

  1. Insert the directive upon the success of the ajax call. You can create an angular.element("myDirective") and then insert it into the DOM and then run $(compile) on that element. The data that is returned from the ajax call can be stored either in the controller or in a constant or local storage or anything you can think of.
  2. Create a synchronous call... I know horrible
  3. Recompile the directive upon completion of the ajax call. Similar to 1 but in this case we run the directive twice not once.
  4. The .children property of the tree can be set via a watcher that kicks in when the ajax call succeeds. Not sure if dynatree's api has a way to dynamically insert data?? I think it does not sure
climboid
  • 6,932
  • 14
  • 44
  • 71