1

There's this template that I call multiple times on the same page:

<div ng-controller="templateController">
      <div class="source">
        <div ng-repeat="item in info">
            <div class="content" data-value="{{item.ID}}">{{item.name}}</div>
        </div>
    </div>
    <br style="clear:both" />
    <div class="receiver"></div>

</div>

and then I want to select all the elements with class="content" within each template scope in order to manipulate them. How can I achieve this using JS?

EDIT :

Plunker

In this planker the console.log should print "1" twice and its printing "1" and then "2" when the template loads the second time

N.Car
  • 492
  • 1
  • 4
  • 14
  • 4
    Please include attempted solutions, why they didn't work, and the expected results. That would really help us to figure out the issue with your code. Thanks! – palaѕн Oct 20 '17 at 15:29
  • What initiates the manipulation? Button press? So each template has it's own controller which has it's own scope? Are you saying you need to manipulate the info variable for each instance of this? – user441521 Oct 20 '17 at 15:34
  • @palaѕн check the plunker and the EDIT – N.Car Oct 20 '17 at 15:37
  • @user441521 check the EDIT please – N.Car Oct 20 '17 at 15:37
  • Why would you expect it to print 1 twice? You have 2 elements with class of "source" in your html. Best not to manipulate the DOM in controllers. What kind of manipulation are you looking to do? – user441521 Oct 20 '17 at 15:39
  • I want to manipulate only one source class within the template which there is just 1 – N.Car Oct 20 '17 at 15:43
  • There is an ng-class directive which you could assign to a variable in your controller on it's scope. What is the criteria for knowing which instance of the template you want to manipulate? – user441521 Oct 20 '17 at 15:45

2 Answers2

3

After more explanation here is a working example:

https://plnkr.co/edit/n5GOd6MDLyvG4ZAsuLvf?p=preview

The main idea is creating 2 lists and iterating over both and just moving data around between them on click.

angular.module("demo", []);

angular
  .module("demo")
  .controller("demoController", ["$scope", function($scope) {

  }]);

angular
  .module("demo")
  .controller("templateController", ["$scope", "$timeout", function($scope, $timeout) {
            $scope.sourceList = [
            {
                name: "john",
                ID: 1
            },
            {
                name: "Edward",
                ID: 0
            },
            {
                name: "Carl",
                ID: 2
            }
        ];

        $scope.receiverList = [
            {
                name: "Bob",
                ID: 1
            }
        ];

        $scope.moveToReceiver = function(item){
          $scope.receiverList.push(item);

          $.each($scope.sourceList, function(i){
            if($scope.sourceList[i].name == item.name){
              $scope.sourceList.splice(i, 1);
              return false;
            }
          });
        }
  }]);
user441521
  • 6,942
  • 23
  • 88
  • 160
  • Each template is meant for when the user clicks on the div "content" it travels from "source" to "receiver". So that is why I just want to select each template's "source" class and not the whole document. Otherwise it would append to every "receiver" class in the document – N.Car Oct 20 '17 at 15:52
  • Just so I fully understand, if I click 'Carl' for example you want the 'Carl' div to move from 'source' to 'receiver'? – user441521 Oct 20 '17 at 15:58
  • Yes. but only within the template. not to all existing "receiver"s – N.Car Oct 20 '17 at 16:00
  • 1
    Each template you have has it's own controller instance. I would make 2 arrays in the controller. Name one sourceList and the other receiverList. Assign ng-click on the content div and pass in the item.name to it. The inside this function you can remove from one list and add to the other. Then in your template do the same ng-repeat for the receiver class. – user441521 Oct 20 '17 at 16:02
  • Yeah, I think that will do it! Thank you for your time and help :) – N.Car Oct 20 '17 at 16:05
  • You're welcome. I've updated with a working forked example. In angular you want to think in terms of data vs manual DOM manipulation. Manipulate your data and then react to the data in the template. – user441521 Oct 20 '17 at 16:13
  • Although this doesn't really answer the original question it definitely solved my issue. Thank you. – N.Car Oct 20 '17 at 16:31
2

Most of the time you do not want to do DOM manipulation in Angularjs and instead hook into events with your controller. If you have to do DOM manipulation in AngularJS you would use directives
Docs on Creating a Directive that Manipulates the DOM

You could then use your link function to grab the children of your directive's element

function link(scope, element, attrs) {
    var content = angular.element(element[0].querySelector('.content'));
}

https://stackoverflow.com/a/17329630/2033671