Mar
Mar

Reputation: 1606

How to manipulate DOM elements with Angular

I just can't find a good source that explains to me how to manipulate DOM elements with angular:

How do I select specific elements on the page?

<span>This is a span txt1</span>
<span>This is a span txt2</span>
<span>This is a span txt3</span>
<span>This is a span txt4</span>

<p>This is a p txt 1</p>

<div class="aDiv">This is a div txt</div>

Exp: With jQuery, if we wanted to get the text from the clicked span, we could simple write:

$('span').click(function(){
    var clickedSpanTxt = $(this).html(); 
    console.log(clickedSpanTxt);
});

How do I do that in Angular?

I understand that using 'directives' is the right way to manipulate DOM and so I am trying:

var myApp = angular.module("myApp", []);

myApp.directive("drctv", function(){

  return {
    restrict: 'E',
    scope: {},
    link: function(scope, element, attrs){
      var c = element('p');
      c.addClass('box');
    }
  };
}); 

html:

<drctv>
<div class="txt">This is a div Txt</div>

<p>This is a p Txt</p>

<span>This is a span Txt </span>
</drctv>

How do I select only 'p' element here in 'drctv'?

Upvotes: 1

Views: 2453

Answers (4)

IxDay
IxDay

Reputation: 3707

ng-click is the simpler solution for that, as long as I do not really understand what you want to do I will only try to explain how to perform the same thing as the one you have shown with jquery.

So, to display the content of the item which as been clicked, you can use ng-click directive and ask for the event object through the $event parameter, see https://docs.angularjs.org/api/ng/directive/ngClick

so here is the html:

<div ng-controller="foo">
  <span ng-click="display($event)" >This is a span txt1</span>
  <span ng-click="display($event)" >This is a span txt2</span>
  <span ng-click="display($event)" >This is a span txt3</span>
  <span ng-click="display($event)" >This is a span txt4</span>

  <p>This is a p txt 1</p>

  <div class="aDiv">This is a div txt</div>
</div>

and here is the javascript

var myApp = angular.module("myApp", []);

myApp.controller(['$scope', function($scope) {
  $scope.display = function (event) {
    console.log(event.srcElement.innerHtml);
    //if you prefer having the angular wrapping around the element
    var elt = angular.element(event.srcElement);
    console.log(elt.html());
  }
}]);

If you want to dig further in angular here is a simplification of what ng-click do

.directive('myNgClick', ['$parse', function ($parse) {
  return {
    link: function (scope, elt, attr) {
      /*
       Gets the function you have passed to ng-click directive, for us it is 
       display
       Parse returns a function which has a context and extra params which 
       overrides the context
      */
      var fn = $parse(attr['myNgClick']);

      /* 
      here you bind on click event you can look at the documentation
      https://docs.angularjs.org/api/ng/function/angular.element
      */
      elt.on('click', function (event) {

        //callback is here for the explanation
        var callback = function () {

          /*
           Here fn will do the following, it will call the display function
           and fill the arguments with the elements found in the scope (if 
           possible), the second argument will override the $event attribute in 
           the scope and provide the event element of the click
          */
          fn(scope, {$event: event});
        }

        //$apply force angular to run a digest cycle in order to propagate the 
        //changes
        scope.$apply(callback);
      });
    }
  }
}]);

plunkr here: http://plnkr.co/edit/MI3qRtEkGSW7l6EsvZQV?p=preview if you want to test things

Upvotes: 0

Ben Heymink
Ben Heymink

Reputation: 1700

To Answer your first question, in Angular you can hook into click events with the build in directive ng-click. So each of your span elements would have an ng-click attribute that calls your click function:

<span ng-click="myHandler()">This is a span txt1</span>
<span ng-click="myHandler()">This is a span txt2</span>
<span ng-click="myHandler()">This is a span txt3</span>
<span ng-click="myHandler()">This is a span txt4</span>

However, that's not very nice, as there is a lot of repetition, so you'd probably move on to another Angular directive, ng-repeat to handle repeating your span elements. Now your html looks like this:

<span ng-repeat="elem in myCollection" ng-click="myHandler($index)">This is a span txt{{$index+1}}</span>

For the second part of your question, I could probably offer an 'Angular' way of doing things if we knew what it was you wanted to do with the 'p' element - otherwise you can still perform jQuery selections using jQuery lite that Angular provides (See Jamie Dixon's answer).

If you use Angular in the way it was intended to be used, you will likely find you have no need to use jQuery directly!

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691655

You should avoid DOM manipulation in the first place. AngularJS is an MVC framework. You get data from the model, not from the view. Your example would look like this in AngularJS:

controller:

// this, in reality, typically come from the backend
$scope.spans = [
    {
        text: 'this is a span'
    },
    {
        text: 'this is a span'
    },
    {
        text: 'this is a span'
    }
];

$scope.clickSpan = function(span) {
    console.log(span.text);
}

view:

<span ng=repeat="span in spans" ng-click="clickSpan(span)">{{ span.text }}</span>

Upvotes: 0

Jamie Dixon
Jamie Dixon

Reputation: 53991

Since element is a jQuery-lite element (or a jQuery element if you've included the jQuery library in your app), you can use the find method to get all the paragraphs inside : element.find('p')

Upvotes: 1

Related Questions