Purpose of $element and $ attrs in component controllers with angularJS components 1.5
Asked Answered
U

2

28

I am working on getting up to speed with 1.5 angular components. I have been following todd Motto's videos to get a start on components along with angular's documentation https://docs.angularjs.org/guide/component.

At this point it seems components are taking the place of directives that use controllers, but in our 1.5 code we still would use directives for dom manipulation.

What is the purpose of $element, $attrs inside of a component controller? These seem to be available for manipulation. Here is the link to the plunker off of the docs. I know they are not using $element, but it is the example I am reading. http://plnkr.co/edit/Ycjh1mb2IUuUAK4arUxe?p=preview

But in code like so ...

 angular
  .module('app', [])
  .component('parentComponent', {
    transclude: true,
    template: `
      <div ng-transclude></div>
    `,
    controller: function () {
      this.foo = function () {
        return 'Foo from parent!';
      };
      this.statement = function() {
        return "Little comes from this code";
      }
    }
  })
  .component('childComponent', {
    require: {
      parent: '^parentComponent'
    },
    controller: function () {

      this.$onInit = function () {
        this.state = this.parent.foo();
        this.notice = this.parent.statement();
      };
    },
    template: `
      <div>
        Component! {{ $ctrl.state }}
        More component {{$ctrl.notice}}
      </div>
    `
  })

What would be the use of $element if we are not manipulating the dom?

Uncritical answered 18/2, 2016 at 15:28 Comment(4)
template function will have Raw DOM and that is not correct place to do DOM manipulation..Alteration
Thanks @PankajParkar I updated my question after reading through the docs again. Definitely get that we are still use link functions and directives in 1.5 with components just do not get $element and its place in a component controller if it isn't for manipulating the domUncritical
I've got a similar query, but more about the $attrs. If I have an input to the component that is never used in the view, but just used for some logic in the controller, should I pass it in through the bindings (good for keeping a consistent API) or inject $attrs into the controller and just read it directly from that (which saves having this property being in the controller, which is possibly tidier). Obviously both work fine. I'm currently trying to answer this in terms of 'what does Angular 2 do?' but have yet to reach a solid conclusion. Did you reach any further conclusion yourself?Ivey
If you want to componets like directives you can inject $element as dependency to controller: controller: function($element) { ... }Deimos
M
24

That's a great question. And I have a simple answer for it.

They take place in components just because Component is syntax sugar around of directive.

Before angular added Components, I was using some kind of component syntax for directives, it was like a convention, that in our project we have two kinds of directives, one is responsible for DOM manipulations, the second is directives with templates which should not manipulate DOM. After components were added, we did not more than changed names.

So Component is nothing more than simple directive which was created as new entity which:

  1. Always has template
  2. Scope is always isolated
  3. Restrict is always Element

I think you can find even more answers in angular sources, but I advise you do not mix these entities, and in case you need to manipulate DOM inside of your component, just use directive inside.

Mauriac answered 19/9, 2016 at 5:18 Comment(0)
B
22

Angular component life cycle hooks allow us to do DOM manipulation inside component controller using $element service

var myApp = angular.module('myApp');
myApp.controller('mySelectionCtrl', ['$scope','$element', MySelectionCtrl]);

myApp.component('mySection', {
    controller: 'mySelectionCtrl',
    controllerAs: 'vm',
    templateUrl:'./component/view/section.html',
    transclude : true
});

function MySelectionCtrl($scope, $element) {
    this.$postLink = function () {
        //add event listener to an element
        $element.on('click', cb);
        $element.on('keypress', cb);

        //also we can apply jqLite dom manipulation operation on element
        angular.forEach($element.find('div'), function(elem){console.log(elem)})

    };

    function cb(event) {
        console.log('Call back fn',event.target);
    }
}

declare component in html

<my-section>
<div class="div1">
    div 1
    <div>
        div 1.1
    </div>
</div>
<div class="div2">
    div 1
</div>

component's partial template(./component/view/section.html)

<div>
<div class="section-class1">
    div section 1
    <div>
        div section 1.1
    </div>
</div>
<div class="section-class1">
    div section 1
</div>

Bristletail answered 15/3, 2017 at 18:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.