2

I have a set of elements that when clicked needs to append a dom element to its nearest class data-here instead of element that was clicked. How do i get it done? Is there a method similar to .closest() to get it working..Here is the sample plunker code -> http://plnkr.co/edit/6VQwGcpX7zsjDSGc3mHp?p=preview

 <div ng-repeat="n in [5, 4, 3, 2, 1] " style="border:solid 1px;" ng-click="clickme($event)">
         Click me!
      <div class="user">User
        <div class="chata">
          Chat Data
        </div>
        </div>
      <div class="wresponse">Response Data </div>
      <div class="data-here" style="border:solid 1px;">
        Append Here
      </div>
      <br/>
    </div>
meteor
  • 2,518
  • 4
  • 38
  • 52
  • 2
    Please read this. It will make you and your employer much better off. tl;dr... don't manipulate the DOM in a controller. http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background – isherwood Sep 02 '16 at 14:10

1 Answers1

3

Don't manipulate the DOM in a controller! It violates the entire point of AngularJS as an app framework.

Here's how I'd do it.

  1. Use an ng-repeat structure for your appended list of elements. It'll start out empty.
  2. Use a directive or a controller function to handle the click event. Add to the view model on click, which will automatically update the view (and your ng-repeat structure).

Here's an example.

<div ng-repeat="thing in ctrl.things track by $index" 
  ng-click="ctrl.clickme(thing, $index+1)">
    <button>Click me!</button>

    <div class="user">User
      <div class="chata">
        Chat Data
      </div>
    </div>

    <div class="wresponse">Response Data </div>

    <div ng-repeat="word in thing.words track by $index">
      {{thing.words[$index]}}
    </div>
</div>

app.controller('MainCtrl', function() {
  var ctrl = this;
  ctrl.name = 'World';
  ctrl.things = [{
    words: ["thing one's word"]
  }, {
    words: ["thing two's word"]
  }, {
    words: ["thing three's word"]
  }];

  ctrl.clickme = function(thing, i) {
    thing.words.push('another thing ' + i + ' word');
  };
});

Plunker demo

No DOM manipulation!

Note that I used track by $index in this example to deal with duplicate items in the repeat structure.

Also, look into using controllerAs syntax. It simplifies quite a few things to do with scope.


If you absolutely must manipulate the DOM, do it in a custom directive. This keeps your controller clean and doing only what controllers should do, which is to update the view model.

Community
  • 1
  • 1
isherwood
  • 58,414
  • 16
  • 114
  • 157
  • Great that solves the problem.. I didn't know we could add on the fly attributes like $index in the function :) And actually this was what that was needed in my badly written angular code `$(event.currentTarget).children('.expand-area')` .. Your code is the way to go fwd..Thanks! – meteor Sep 02 '16 at 15:58