D
D
Dmitry Poltavskiy2017-01-28 14:26:00
Angular
Dmitry Poltavskiy, 2017-01-28 14:26:00

AngularJS how to access the this of a child component's controller?

There are two components, it is necessary to call the method of the child
broadcast from the parent , they are not suitable, because this widget can be nested one inside the other, the broadcast will go deep into all the children
. It is also not an option to use services , because there can be several of these widgets, with different settings, for the same reason, the option with the global variable angular and rootscope
also disappears Access is necessary to implement the logic "OnlyOneOpen"
When the user clicks on an item , the isOpen class is added , when he clicks on another item, the previous one must be closed. From the same item`a I can not close the rest
If you have any ideas how to make it smarter, write))

<moto-accordion ng-cloak>
  <moto-accordion-item class="moto-accordion-item panel panel-default">
    <header class="header-text">
      Header
    </header>
    <div class="content-text">
      Content
    </div>
  </moto-accordion-item>
</moto-accordion>

Here is the parent component
angular.module('moto-accordionApp')
.component('motoAccordion', {
  transclude: true,
  template:  '<div ng-transclude></div>',
  bindings: {
    openOnlyOneCheckbox: '=openOnlyOne',
    closeAllButton: '=closeAll'
  },
  controller: [
    '$element',
    '$attrs',
    '$scope',
    'openAccordionService',
    function($element, $attrs, $scope, openAccordionService) {
      this.$onInit = function () {

      };
    }
  ]
});

Here is the child component
angular.module('moto-accordionApp')
.component('motoAccordionItem', {
  transclude: {
    'header': 'header',
    'body': 'div'
  },
  template:
  '<div class="panel-heading header" ng-transclude="header" ng-click="$ctrl.open()"></div>' +
  '<section ng-transclude="body" class="content"></section>',
  require: {
    motoAccordion: '^motoAccordion'
  },
  controller: [
    '$element',
    '$attrs',
    '$scope',
    'openAccordionService',
    function($element, $attrs, $scope, openAccordionService) {
      this.$onInit = function () {
        var vm = this;
        vm.isOpen = false;

        vm.open = function() {
          if(!vm.isOpen) {
            $element.addClass('isOpen');
            vm.isOpen = true;
          }
          else {
            $element.removeClass('isOpen');
            vm.isOpen = false;
          }
        }
      }
    }
  ]
});

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
Nicholas, 2017-01-28
@healqq

Make isOpen a binding that comes from the parent.
Make a method of some kind in the parent controller, which will be bound / obtained through require in child and will make the current element active.
those. in parent:

vm.elements = [ {id: 1, isOpen: false}, {id: 2, isOpen: true}];
vm.onItemClick = function(id) {
    elements.forEach(function(element) {
           element.isOpen = (element.id === id);
    });
}

L
lega, 2017-01-28
@lega

In alight, you can publish an api to control the component https://jsfiddle.net/lega911/vfeL3g6L/
In angular, you can do the same, pass the variable name to the component, the component will already put its api there.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question