how to send an object to angular directive on a check-box - javascript

i am trying to consume iCheck check box using a directive. my directive is setup like this.
.module('app').directive('bootstrapCheck', ['$timeout', '$parse', function ($timeout, $parse) {
return {
compile: function (element, $attrs) {
var icheckOptions = {
checkboxClass: 'icheckbox_minimal',
radioClass: 'iradio_minimal'
};
var modelAccessor = $parse($attrs['ngModel']);
return function ($scope, element, $attrs, controller) {
var modelChanged = function (event) {
$scope.$apply(function () {
modelAccessor.assign($scope, event.target.checked);
});
};
$scope.$watch(modelAccessor, function (val) {
var action = val ? 'check' : 'uncheck';
element.iCheck(icheckOptions, action).on('ifChanged', modelChanged);
});
};
}
};
}]);
my check-boxes are in ng-repeat. i want to send the current object to function to process it further. my html is setup like this.
<input type="checkbox" ng-model="item.isSelected" ng-change="onChangeEvent(item)" bootstrap-check>
modelChanged gets triggered each time i change any check-box. but i am trying to access item inside modelChanged function to process it further. please guide.

You can pass the item to directive scope and access it inside the link function. Along with item you can also pass the onChangeEvent handler to the directive. Try this.
JS
angular.module('app').directive('bootstrapCheck', ['$timeout', '$parse', function ($timeout, $parse) {
return {
scope: {
item: '=',
onChangeEvent: '&'
},
compile: function (element, $attrs) {
var icheckOptions = {
checkboxClass: 'icheckbox_minimal',
radioClass: 'iradio_minimal'
};
var modelAccessor = $parse($attrs['ngModel']);
return function ($scope, element, $attrs, controller) {
var modelChanged = function (event) {
//Here $scope.item will give you the item
//This will trigger the parent controller's onChangeEvent set in the directive markup
$scope.onChangeEvent({ item: $scope.item });
$scope.$apply(function () {
modelAccessor.assign($scope, event.target.checked);
});
};
$scope.$watch(modelAccessor, function (val) {
var action = val ? 'check' : 'uncheck';
element.iCheck(icheckOptions, action).on('ifChanged', modelChanged);
});
};
}
};
}]);
HTML
<input type="checkbox"
ng-model="item.isSelected"
item="item"
on-change-event="onChangeEvent(item)" bootstrap-check>

Related

AngularJS directive that will look at the value of my ngModel then fire off a function in the controller and be available immediately in view

I am trying to use a $scope.quickText(data) function in my controller. The function reviews the parameter 'data' and looks for any codes (ie: .smoke) and then adds that text to the value of the model.
For instance, if the ngModel value was "Completed smoke assessment" and someone types into the 'textarea' or 'text' input .smoke, it would add "patient smokes. Completed smoke assessment". This would be available to see in the view instantly as the user is typing .smoke. The function works but my directive does not.
myApp.directive('gmaEvalQuickText1', ['$timeout', function ($timeout) {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
scope: {
quickTextEvaluate: '&',
},
bindToController: true,
controller: 'gmaController',
controllerAs: 'gc',
link: function ($elem, $ctrl,controller) {
$elem.on('input keyup change', function () {
var val = $elem.val().toString();
var newVal = gc.quickText(val).toString();
$ctrl.$setViewValue(newVal);
$timeout(function () {
$ctrl.$render();
});
});
}
}
}]);
I am very new to AngularJS so I am sure I am doing something wrong.
I figured out how to make it work :)
For those who need the answer:
Directive:
myApp.directive('evalQuickText', ['$timeout', function ($timeout) {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
scope: {
quicktextevalfct: '='
},
link: function ($scope, $elem, attrs, $ctrl) {
$elem.on("keydown keypress", function (event) {
if(event.which === 13) {
var val = $elem.val().toString();
var newVal = $scope.quicktextevalfct(val);
$ctrl.$setViewValue(newVal + "\n");
$timeout(function () {
$ctrl.$render();
});
event.preventDefault();
}
if(event.which === 9) {
var val = $elem.val().toString();
var newVal = $scope.quicktextevalfct(val);
$ctrl.$setViewValue(newVal);
$timeout(function () {
$ctrl.$render();
});
event.preventDefault();
}
});
}
};
}]);
HTML:
eval-quick-text quicktextevalfct="quickTextEvaluate"

pass parameter to angular directive on click

I am trying to get parameter on click using directive.I want to get child data in the click event for checking has child or not.
.....
html
div ng-app="treeApp">
<ul>
<treeparent></treeparent>
</ul>
js
(function () {
var treeApp = angular.module('treeApp', []);
treeApp.directive('treeparent', function () {
return {
restrict: 'E',
template: "<button addchild child='m'>ajith</button><div id='new'></div>"
}
});
treeApp.directive('addchild', function ($compile) {
return {
scope: {
'child':'='
},
link: function (scope, element, attrs) {
debugger;
element.bind("click", function (scope,attrs) {
debugger;
//here i want to get hild ie 'm'
angular.element(document.getElementById('new')).append("<div><button button class='btn btn-default'>new one</button></div>");
});
}
}
});
})();
plz help me
So, i think scope.child is undefined becouse it is overlaps in declaring event.
You can define variable before event binding
link: function (scope, element, attrs) {
var child = scope.child;
element.bind("click", function (scope,attrs) {
// here you can use child
console.log('child', child);
});
}
or declare different argument names
link: function ($scope, $element, attrs) {
element.bind("click", function (scope,attrs) {
// here you can use $scope.child
console.log('$scope.child', $scope.child);
});
}
Is a callback has scope and attrs argument? May be it has only one $event argument?
link: function (scope, element, attrs) {
element.bind("click", function ($event) {
// here you can use child
console.log('child', scope.child);
});
}
Example for call method from directive in parent scope
parent template
<test-dir data-method="myFunc"></test-dir>
<button ng-click="myFunc('world')">click me</button>
or
<button test-dir data-method="myFunc" ng-click="myFunc('world')">click me</button>
directive
.directive('testDir', function() {
return {
scope: {
method: '=',
},
controller : function($scope) {
$scope.method = function(text) {
alert('hello '+text);
};
},
};
})

Set Directive Angular after rendering view

I want to load my Angular Directive when my class change.
I have a directive who get the route and when this directive can get a route she set on a class in a div child.
But when the div child have the class, the directive don't run.
Route directive :
angular.module('myApp').directive('index', ['$rootScope','usersEntity', '$location', '$timeout',function($rootScope,usersEntity, $location, $timeout){
return {
restrict: 'E',
templateUrl: 'index',
replace: true,
controller: function ($scope, $element, $attrs) {
$scope.user = function () {
return usersEntity;
};
$scope.location = function () {
return $location.path().replace('/', '');
};
$rootScope.$on('$locationChangeStart', function (event) {
$scope.routeMap = {
'login': 'users-log'
};
if ($scope.location().length < 1) {
$scope.route = '';
} else {
$.each($scope.routeMap, function (index, value) {
if (index == $scope.location()) {
$scope.route = value;
}
});
}
});
},
link: function() {
}
}
}]);
Thanks and sorry for my perfect English ;)

AngularJS: How do I call a function defined in a directive's scope from a controller?

I need to call a function which belongs to the $scope of a ng-directive used in my Angular application.
Let's say the directive is defined like this:
.directive('my-directive', ['$document', '$timeout', function ($document, $timeout) {
return {
restrict: 'E',
replace: true,
scope: {
// ....
},
controller: ['$scope', function ($scope) {
$scope.myFunction= function (mouseEnter) {
// ...
};
}
};
}]);
I need to call myFunction from my controller (let's call it my-controller) which is the controller of the view where my directive is placed.
Is it possible to do it? (eventually modifying the directive)
EDIT : The already answered question provided (proposed for edit) is similar to mine by it's not clear to me or it doesn't apparently solve the specific problem I proposed.
EDIT 2: starting from Dan M. answer (without taking mouseenter/mouseleave in consideration. just trying to make the two controllers communicate with each other), I broadcasted my event to my directive's controller through $rootScope (as there is there is no parent-child relation between the two controllers) by:
console.log("let's broadcast the event.."); // this is printed
$rootScope.$broadcast('callDirectiveControllersFunction'); // I even tried with $scope in place of $rootScope and $emit in place of $broadcast
and by receving it (within the directive's controller) by:
var myFunction = function(){
// ...
}
$scope.$on('callDirectiveControllersFunction', function (){
console.log("event received"); // this is not printed
callMyFunction();
});
// I even tried using $rootScope in place of $scope
However in no case (see comments in code) the event is received
You can call a controller function inside the link block. You can also $emit an event in the directive and listen to the it in the controller (maybe there is a use case for that).
It seems that you want to call it on mouseenter. You can do that by binding to the mouseenter event in the directive link. The catch is you need to $apply the changes.
Take a look at the following piece of code, which contains all 3 examples: http://jsbin.com/cuvugu/8/. (also pasted below)
Tip: You might want to pay attention to how you name your directives. To use a directive as my-directive you need to name it as myDirective.
var app = angular.module('App', []);
app.directive('myDirective', function () {
function directiveLink(scope){
scope.$emit('customEvent');
}
return {
restrict: 'EA',
scope: {},
link: directiveLink,
controller: function ($scope) {
$scope.bar = 'bar';
$scope.myFunction = function () {
$scope.bar = 'foobar1';
};
$scope.$on('customEvent', function (){
$scope.myFunction();
});
},
template: "Foo {{bar}}"
};
});
app.directive('anotherDirective', function () {
function directiveLink(scope){
scope.myFunction();
}
return {
restrict: 'EA',
scope: {},
link: directiveLink,
controller: function ($scope) {
$scope.bar = 'bar';
$scope.myFunction = function () {
$scope.bar = 'foobar2';
};
},
template: "Foo {{bar}}"
};
});
app.directive('mouseDirective', function () {
function directiveLink(scope, element){
element.bind('mouseenter', function(){
scope.$apply(function(){
scope.myFunction();
});
});
element.bind('mouseleave', function(){
scope.$apply(function(){
scope.myOtherFunction();
});
});
}
return {
restrict: 'EA',
link: directiveLink,
controller: function ($scope) {
$scope.bar = 'no';
$scope.myFunction = function () {
$scope.bar = 'yes';
};
$scope.myOtherFunction = function () {
$scope.bar = 'no';
};
},
template: "Mouse Enter: {{bar}}"
};
});
I also included an example with a distinct controller in the JS Bin link. That doesn't really change anything, but it seems to be an important part of your question. Here's the code block:
var app = angular.module('App', []);
app.controller('myController', function($scope){
$scope.bar = 'foo';
$scope.myFunction = function(){
$scope.bar = 'foobar3';
};
});
app.directive('lastDirective', function () {
function directiveLink(scope){
scope.myFunction();
}
return {
restrict: 'EA',
scope: {},
link: directiveLink,
controller: 'myController',
template: "Foo {{bar}}"
};
});

angular.js directive two-way-binding scope updating

I wanted to use a directive to have some click-to-edit functionality in my front end.
This is the directive I am using for that: http://icelab.com.au/articles/levelling-up-with-angularjs-building-a-reusable-click-to-edit-directive/
'use strict';
angular.module('jayMapApp')
.directive('clickToEdit', function () {
return {
templateUrl: 'directives/clickToEdit/clickToEdit.html',
restrict: 'A',
replace: true,
scope: {
value: '=clickToEdit',
method: '&onSave'
},
controller: function($scope, $attrs) {
$scope.view = {
editableValue: $scope.value,
editorEnabled: false
};
$scope.enableEditor = function() {
$scope.view.editorEnabled = true;
$scope.view.editableValue = $scope.value;
};
$scope.disableEditor = function() {
$scope.view.editorEnabled = false;
};
$scope.save = function() {
$scope.value = $scope.view.editableValue;
$scope.disableEditor();
$scope.method();
};
}
};
});
I added a second attribute to the directive to call a method after when the user changed the value and then update the database etc. The method (´$onSave´ here) is called fine, but it seems the parent scope is not yet updated when I call the method at the end of the directive.
Is there a way to call the method but have the parent scope updated for sure?
Thanks in advance,
Michael
I believe you are supposed to create the functions to attach inside the linking function:
Take a look at this code:
http://plnkr.co/edit/ZTx0xrOoQF3i93buJ279?p=preview
app.directive('clickToEdit', function () {
return {
templateUrl: 'clickToEdit.html',
restrict: 'A',
replace: true,
scope: {
value: '=clickToEdit',
method: '&onSave'
},
link: function(scope, element, attrs){
scope.save = function(){
console.log('save in link fired');
}
},
controller: function($scope, $attrs) {
$scope.view = {
editableValue: $scope.value,
editorEnabled: false
};
$scope.enableEditor = function() {
$scope.view.editorEnabled = true;
$scope.view.editableValue = $scope.value;
};
$scope.disableEditor = function() {
$scope.view.editorEnabled = false;
};
$scope.save = function() {
console.log('save in controller fired');
$scope.value = $scope.view.editableValue;
$scope.disableEditor();
$scope.method();
};
}
};
});
I haven't declared the functions inside the controller before, but I don't see why it wouldn't work.
Though this question/answer explain it Link vs compile vs controller
From my understanding:
The controller is used to share data between directive instances, not to "link" functions which would be run as callbacks.
The method is being called but angular doesn't realise it needs to run the digest cycle to update the controller scope. Luckily you can still trigger the digest from inside your isolate scope just wrap the call to the method:
$scope.$apply($scope.method());

Categories

Resources