1

I want to pass a function from the parent component to the child component and give it an argument that has also been given from the parent component to the child. (showOrHideSub="item.showOrHideSub(item.id)" ) I have tried different ways and it doesn't work.

This is my html (parent component) in which I want to use the child component tag. vm is the controller of this scope:

<li ng-repeat="item in vm.menuItems">
<menu-item-comp id="item.id" showOrHideSub="item.showOrHideSub(item.id)" />
</li>

Here is the child component template. itemVm is the controller of this component:

<div id="{{itemVm.id}}" ng-mouseover="itemVm.showOrHideSub(itemVm.id)">
<div id="itemVm.subId" class="menuItemImgText">{{ itemVm.label }}</div>

Here is the child component js:

    module.component('menuItemComp', {
        templateUrl: '/webapp/app/components/menu/menuItemComponent.html',
        bindings: {
            id: '<',
            showOrHideSub: '&',
            label: '<',
            submenuId: '<',
        },
        controllerAs: 'itemVm',
        controller: ['LogService', menuCtrl]
    });

    function menuCtrl($scope, LogService) {

        var itemVm = this;
    }

And here is the showOrHideSub() function in the parent controller:

    vm.showOrHideSub = function (submenu) {
        console.log(submenu);
        switch (submenu) {
            case 'menuItemDivPositions':
                console.log('position');
                break;
            case 'menuItemDivOther':
                console.log('other');
                break;
        }
    }

I know that in directives the way to do it is by object mapping such as showOrHideSub="item.showOrHideSub({item: item.id})" but it doesn't seem to work in component.

2 Answers 2

1

If you're working with components, you have to do it the components way. It looks like you have a hierarchy of components (child / parent).

Functions and attributes inside the parent can be inherited by children using require.

require: {
  parent: '^^parentComponent'
}

This way, if the parent defines a function showOrHideSub, the children can call it directly using this.parent.showOrHideSub(xxx)

This is not the only way to solve your issue but this is the right way™ for the architecture you chose.

var parentComponent = {
    bindings: {},
    controller: ParentController,
    template: `
      <li ng-repeat="item in $ctrl.menuItems">
        <child-component item="item"></child-component>
      </li>
    `
};
var childComponent = {
    bindings: {
      item: '<'
    },
    require: {
      parent: '^^parentComponent'
    },
    controller: ChildController,
    template: '<button ng-click="$ctrl.buttonClick($ctrl.item.id);">{{$ctrl.item.name}}</button>'
};
function ParentController() {
  this.menuItems = [{id:1, name:"item1"},{id:2, name:"item2"}];
  this.showOrHideSub = function(param) {
     console.log("parent function called with param: " + param);
  }
}
function ChildController() {
  var vm = this;
  this.buttonClick = function(id) {
    vm.parent.showOrHideSub(id);
  }
}

angular.module('app', []);
angular.module('app')
    .component('parentComponent', parentComponent)
    .component('childComponent', childComponent);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="app">
  <parent-component></parent-component>
</div>

Sign up to request clarification or add additional context in comments.

Comments

0

Change 'item' to 'vm' in below code. You are binding the item function 'showOrHideSub(item.id)' which doesn't exist. Here is the updated code.

<li ng-repeat="item in vm.menuItems">
   <menu-item-comp id="item.id" showOrHideSub="vm.showOrHideSub(item.id)" />
</li>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.