how to pass callback funtion to Angular JS dirctive - angularjs

I am trying to create a footer directive that I can pass an array of button objects to.
here is my array...
$scope.buttons = [
{
btnLabel: "Close",
btnClass: "btn-p2 pull-left",
show: true,
disabled: false,
callback: function(){console.log('close...');},
role: ''
},
{
btnLabel: "Save",
btnClass: "btn-p1 pull-right",
show: true,
disabled: true,
callback: saveTest,
role: ''
}
];
I have most of it working the way I want but, having issue with passing the callback functions. I am seeing the buttons but when I click the callback functions are not getting called. Any ideas on how to pass the callback functions?
Thanks and regards,
dj

Because saveTest is not defined in your scope, directive doesn't have access to it. So either you have to defined them on the scope and use them there, or you can pass them as directives attributes in its own scope:
First way:
$scope.saveTest = function () {
}
And then you can use the parent scope in your directive:
app.directive('someDirective', function() {
return {
restrict: 'E'
templateUrl: "..."
}
})
By not defining the scope in directive, you are saying I want to use parent scope here.
Second way:
app.directive('someDirective', function() {
return {
restrict: 'EA',
scope: {
saveTest: '&',
close: '&'
},
templateUrl: "..."
}
})
Now that we have defined them in the directive we have to pass them from html like this:
<div some-directive save-test="saveTest" close="close"></div>

Related

angularjs - Passing scope parameter to component

We can pass scope parameter to a directive
app.directive('appInfo', function() {
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'js/directives/appInfo.html'
};
});
and use it as follows in a view:
<app-info info="app"></app-info>
A component can be used as a directive too:
<component-info></component-info>
But can we pass to it a scope parameter same as info="app" ?
Yes, for a component you'll use bindings instead of scope. So your component definition will look somewhat like this:
app.component('componentInfo', {
bindings: {
info: '='
},
// ... and so on
});

AngularJS Directive interacting with a parent function including params

in my main controller I have a function to set messages on the page:
function setMessageState(showSuccess, showError, message) {
vm.showSuccessMessage = showSuccess;
vm.showErrorMessage = showError;
vm.message = message;
}
Within my main controller and service I relay messages to the user by calling this if the service succeeds or fails in retrieving data.
I have moved one of my repeaters into a directive which handles iteration of tabular data but part of this relies on calling the setMessageState function and feeding back the parameters into the main VM.
Can anyone assist in how I can call my setMessageState function from the directive with the included params?
I did try including setMessageState: "&" but while dupressing the issue of setMessageState is not defined it didn't call the function
My Directive is:
(function () {
'use strict';
//Define the Controller
angular
.module("tpAccStatus")
.directive("tpAccStatusTransactionRow", tpAccStatusTransactionRow);
function tpAccStatusTransactionRow() {
return {
scope: {
trans: "=tpAccStatusTransactionRow",
accountNumber: "="
},
restrict: "A",
replace: true,
templateUrl: "tpAccStatusTransactionRow.directive.html",
bindToController: true,
controller: "tpAccStatusTransactionRowCtrl",
controllerAs: "transCtrl"
};
}
})();
And my Directive Controller has a function which calls (needs to call) upon that parent controller function:
function requestStatementErrored(error) {
vm.busy = false;
vm.setMessageState(false, true, "Problem obtaining details");
}
Thanks
The directive wont know anything about vm in your parent, instead, you can add a scope property to your directive that is then bound to a reference to the function in your parent
So:
scope: {
trans: "=tpAccStatusTransactionRow",
accountNumber: "=",
messageStateFn: "="
}
Then when using your directive, you can set like so:
<tr tpAccStatusTransactionRow messageStateFn="vm.setMessageState"></tr>
And in your directive controller:
function requestStatementErrored(error) {
scope.setMessageState(false, true, "Problem obtaining details");
}
You may do like this from your directive,
scope: {
trans: "=tpAccStatusTransactionRow",
accountNumber: "=",
setMessageState: '&'
},
function requestStatementErrored(error) {
vm.setMessageState({showSuccess: false, showError: true, message: "Problem obtaining details");
},
and in HTML,
<tr tpAccStatusTransactionRow set-message-state="vm.setMessageState"></tr>

AngularJS ES6 ui-grid directive scope, ng-click dont work

I have a chain directive with angularJS and ES6 and want to use ui-grid.
The grid is shown with the correct columns and data, thats fine.
But ng-click donĀ“t work in the cellTemplate. Nothing happens.
Also i try to check the grid object with console.log(grid) and grid is undefined.
Who can i use the cellTemplate to call the openDetail method?
export default function ChainsDirective() {
class ChainsDirective {
/*#ngInject*/
constructor(chainsService, $state) {
this.chainsServiceLoadChains = chainsService.loadChains.bind(chainsService);
this.gridOptions = {
enableColumnMenus: false,
columnDefs: [
{
name: 'id',
visible: false
},
{
name: 'name',
displayName: 'Kette',
cellTemplate: '<div class="ui-grid-cell-contents"><a onclick="console.log(grid)" ng-click="grid.appScope.openDetail(row.entity.id)">{{row.entity.name}}</a></div>'
}
]
};
this.$stateGo = $state.go.bind($state);
this.fetch(); // best practice initiales laden in einer Funktion zu kapseln
}
/**
* #param int chainId
*/
openDetail(chainId) {
this.$stateGo('chainDetail', {chainId})
}
fetch() {
return this.chainsServiceLoadChains().then(data => {
this.gridOptions.data = data;
})
}
}
return {
restrict: 'E',
template: '<div ui-grid="chains.gridOptions" external-scopes="$scope" class="grid"></div>',
scope: {},
bindToController: {},
controller: ChainsDirective,
controllerAs: 'chains'
}
}
I've never used ui-grid directive. But it seems that you need to access your controller by its name, since you have declared it with the "controller as" syntax.
So in your ng-click you need to reference the controller on the scope with its name chains:
ng-click="grid.appScope.chains.openDetail(row.entity.id)"

Call a function inside the directive

Trying to call a function inside the directive:
angular.module('abc').directive('autocomp', function () {
return {
replace: true,
scope: true,
controller: 'Controller',
controllerAs: 'ctrl',
srchtxt: '#',
scope: {
src: '&'
},
templateUrl: '/dom/abc/auto.html',
link: function (scope, element, attrs) {
scope.$watch('srchtxt', function () {
scope.src(scope.srchtxt});
});
}
}
});
==========================================================================
Method inside the controller:
function search(srchtxt) {
console.log('srchText:', srchText);
}
===========================================================================
HTML:
<abc src="rc.search()"></abc>
I am writing a directive for the md-autocomplete control to which method name can be passed as attributes from the HTML pagee, and then try to execute the method inside the directive.
There's a watch on the textchange in the control in which I call the method to be executed (scope.src(scope.srchText}))
When I type in something into the autocomplete control I get the following error:
TypeError: Cannot use 'in' operator to search for 'rc' in g
Could any one please suggest on what am I missing or doing wrong ?
When you use & to bind controller method into directive, you have to declare exact parameter in your html like
<sml-auto-complete datasrc="cr.query(searchText)"></sml-auto-complete>
// ^
Then when you call this method from directive you need to pass the parameter as object like
scope.$watch('searchText', function () {
scope.datasrc({searchText: scope.searchText}); //not simply scope.datasrc(scope.searchText)
});
Check this demo

ng-show not working inside directive template

I would like to do something like this
fiddle, making the text disappear and reappear with every click.
Problem is, it seem that with an isolated scope you can't have access to the controller scope. I solved it in the link function, handling there click event and setting my "showMe" flag using scope.$apply, like:
scope.$apply('showMe = false');
Is this the right way to go or there is some more elegant method?
Here you go (http://jsfiddle.net/66d0t7k0/1/)
Put your click handler in the link function and expose showMe to the scope
app.directive('example', function () {
return {
restrict: 'E',
template: '<p ng-show=\"showMe\">Text to show</p><button ng-click=\"clickMe()\">Click me</button>',
scope: {
exampleAttr: '#'
},
link: function (scope) {
scope.clickMe = function () {
scope.showMe = !scope.showMe;
};
}
};
});
To expand on apairet's answer, since your directive is using an isolated scope, you could handle all of that in the template itself like so:
app.directive('example', function () {
return {
restrict: 'E',
template: '<p ng-show=\"showMe\">Text to show</p><button ng-init=\"showMe = false\" ng-click=\"showMe = !showMe\">Click me</button>',
scope: {
exampleAttr: '#'
},
link: function (scope) {
}
};
});
Another consideration is to use ng-if rather than ng-show as it doesn't render the element in the DOM until the expression evaluates to true.
You can hide the scope in the directive by setting scope: false
You can then put all your function in the main controller scope
angular.module('appMyApp').directive('appMyAppItem', function() {
return {
transclude: true,
templateUrl: 'link/to/url',
controller: 'appMyAppController',
scope: false
}
});
angular.module('appMyApp').controller('appMyAppController', ['$scope', function($scope){
$scope.showItem = true;
$scope.toggleItem = function(){
$scope.showItem = !$scope.showItem;
};
}]);
Hope this helps

Resources