AngularJs passing a value to a directive - angularjs

I'm trying to pass a value to a directive. The directive is used to integrate a jquery plugin Knob
JSFIDDLE: http://jsfiddle.net/Tropicalista/TH87t/93/
I have this code:
var App = angular.module('Knob', []);
App.controller('myCtrl', function($scope) {
$scope.number = 24;
})
App.directive('knob', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$(element).knob().val(scope.number);
console.log(attrs)
}
};
});

The problem is that knob() doesn't return the element. Use this instead:
link: function(scope, element, attrs) {
$(element).val(scope.number).knob();
}
Here's your fiddle: http://jsfiddle.net/TH87t/94/

I used your question as reference for a fully bi-direction binding. For a working version with angular 1.2.1 see http://jsfiddle.net/sander_van_dam/m5YJu/
App.directive('knob', function() {
return {
require: 'ngModel',
scope: { model: '=ngModel' },
controller: function($scope, $element, $timeout) {
var el = $($element);
$scope.$watch('model', function(v) {
var el = $($element);
el.val(v).trigger('change');
});
},
link: function($scope, $element, $attrs,$ngModel) {
var el = $($element);
el.val($scope.value).knob(
{
'change' : function (v) {
$scope.$apply(function () {
$ngModel.$setViewValue(v);
});
}
}
);
}
}
});

Related

Access angular controller from directive using require

In a directive i want to require a controller but i get the error that the controller can't be found. I am sure it is a small thing or maybe it is not possible the way i want to do it.
angular.module('myApp', []);
angular.module('myApp').controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
//some function here returning data
}]);
angular.module('myApp').directive('yoloswag', function() {
return {
require: ['^?ngModel', '^GreetingController'],
restrict: 'A',
scope: {
},
link: function(scope, element, attrs, controllers) {
var modelCtrl = controllers[0],
greetingsCtrl = controllers[1];
console.log(controllers)
}
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="GreetingController">
{{ greeting }}
<div yoloswag>test</div>
</div>
</div>
What am i doing wrong?
Thank you so much!
Your code does not having and dependency with your main module, that's why you are getting that error.
Your code should be the following
angular.module('myApp', [])
.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
//some function here returning data
}])
.directive('yoloswag', function() {
return {
require: ['^?ngModel', '^GreetingController'],
restrict: 'A',
scope: {
},
link: function(scope, element, attrs, controllers) {
var modelCtrl = controllers[0],
greetingsCtrl = controllers[1];
console.log(controllers)
}
};
});
or set a variable for main module then you can add controller and directive with the main module like,
var MainModule = angular.module('myApp', []);
MainModule.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
//some function here returning data
}]);
MainModule.directive('yoloswag', function() {
return {
require: ['^?ngModel', '^GreetingController'],
restrict: 'A',
scope: {
},
link: function(scope, element, attrs, controllers) {
var modelCtrl = controllers[0],
greetingsCtrl = controllers[1];
console.log(controllers)
}
};
});
You can use controller property of directive :
make sure don't update property in link function.
return {
restrict: 'A',
scope: {
},
controller : 'GreetingController',
link: function(scope, element, attrs) {
var modelCtrl = controllers[0],
greetingsCtrl = controllers[1];
console.log(controllers)
}
};

How can I pass variables from an isolated scope directive to a child?

I have two isolated scope directives. Ideally I like both to work independently and not require any custom templates. The first directive is going to be page scroll watcher, when it hits a certain point I want it to trigger an update in the other directive. Is it possible for a child directive to watch a variable in the parent directive?
I've created a simple plunkr to illustrate the issue, http://plnkr.co/edit/wwfBzmemyrj1r1R54riM?p=preview
/*
<div ng-outer>Outer directive {{myvar}}
<div ng-inner="myvar">Inner directive</div>
</div>
*/
app.directive('ngOuter', [ '$timeout', function ($timeout) {
var directive = {
restrict: 'A'
,scope:{}
}
directive.link = function (scope, element, attrs) {
$timeout(function(){
scope.myvar = "test 001"
},1000)
}
return directive;
}]);
app.directive('ngInner', [ function () {
var directive = {
restrict: 'A'
,scope:{ data: '=ngInner', myvar: '=myvar' }
}
directive.link = function (scope, element, attrs) {
scope.$watch('data', function(newVal, oldVal){
if(newVal)
element.text("new inner val", newVal);
});
scope.$watch('myvar', function(newVal, oldVal){
if(newVal)
element.text("new myvar", newVal);
});
}
return directive;
}]);
Solved this issue by using
angular.element(element.parent()).isolateScope();
The child directive can access the scope of the parent directive and watch variables etc.
http://plnkr.co/edit/RAO6q81ZE4tClMDMiLFb?p=preview
First approach of passing variable from parent directive to the child is by using an 'attr' in child scope with '#' and initialize it in parent controller as following:
var app = angular.module('app', []);
app.directive('ngOuter', [ '$timeout', function ($timeout) {
return{
restrict: 'E',
scope:{},
template: '<ng-inner attr="{{myvar}}">Inner directive {{myvar}}</ng-inner>',
controller: ['$scope', function($scope) {
$scope.myvar = "test 001";
}],
link: function (scope, elem, attrs) {
}
}
}]);
app.directive('ngInner', [ function () {
return{
restrict: 'E',
scope:{'attr' : "#"},
link: function (scope, element, attrs) {
console.log(scope.attr);
}
}
}]);
html:
<ng-outer></ng-outer>
2nd approach is utilizing a function in a parent controller which returns the "myvar" value and call that function in child directive:
app.directive('ngOuter', [ '$timeout', function ($timeout) {
return{
restrict: 'E',
scope:{},
template: '<ng-inner attr="{{myvar}}">Inner directive {{myvar}}</ng-inner>',
controller: ['$scope', function($scope) {
$scope.myvar = "test 001";
this.getMyvar = function() {
return $scope.myvar;
};
}],
link: function (scope, elem, attrs) {
}
}
}]);
app.directive('ngInner', [ function () {
return{
restrict: 'E',
require: '^ngOuter',
scope:{'attr' : "#"},
link: function (scope, element, attrs, parentDirCtrl) {
console.log(parentDirCtrl.getMyvar());
}
}
}]);
3rd Approach: you can inject a service to both inner and outer directives.Then use the service.
var app = angular.module('app', []);
app.service('myService', [
function() {
var service = {
myvar: 'test001',
setMyVar: function(value) {
this.myvar = value;
},
getMyVar: function() {
return this.myvar;
}
}
return service;
}
]);
app.directive('ngOuter', ['$timeout', 'myService',
function($timeout, myService) {
var directive = {
restrict: 'A',
scope: {}
}
directive.link = function(scope, element, attrs) {
$timeout(function() {
scope.myvar = myService.getMyVar();
}, 1000)
}
return directive;
}
]);
app.directive('ngInner', ['myService',
function(myService) {
var directive = {
restrict: 'A',
scope: {}
}
directive.link = function(scope, element, attrs) {
var variable = myService.getMyVar();
console.log("myvar", variable);
}
return directive;
}
]);

Using Controllers In Directives In AngularJS

my directive:
angular.module('matrixarMatrice', []).directive('mtxMatriceForm', function () {
return {
restrict: 'E',
templateUrl: 'views/matrice/matrice.html',
scope: {
matrix: '=',
isclicked: '=',
selectedprice: '&'
},
link: function (scope, element, attrs) {
...
scope.selected = function (prices) {
scope.selected.id = prices.id;
scope.selectedprice(prices);
};
}
};
});
my controller:
$scope.selectedprice = function (prices) {
console.log(prices);
};
my html:
<mtx-matrice-form matrix="matrix " isclicked="isclicked" selectedprice="selectedprice(prices)"></mtx-matrice-form>
In my directive when i select item i call my controller.
I want to exploit my object prices, but the problem i have at the moment is i have an undefined in my controller.
Does anyone know the correct way of doing this?
This is the one option that you can use to include controller inside a directive! There are other options as well. Hope it helps!
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'Lorem';
});
app.directive('directives', function() {
return {
restrict: 'E',
controller: function($scope, $element){
$scope.name = $scope.name + "impsum";
},
link: function(scope, el, attr) {
scope.name = scope.name + "Ipsum";
}
}
})
i have found this solution:
in my directive:
...
scope.selected = function (prices) {
scope.selected.id = prices.id;
scope.selectedprice({prices: prices});
};
...

AngularJS - cannot access directive controller in another directive

I have two angularjs directives (extWindow and taskBar) and want to inject taskBar's controller into extWindow in order to access it's scope. Because they don't share the same scope I used
require : '^$directive'
syntax to include it.
Doing so I could get rid of the error 'Controller 'taskBar', required by directive 'extWindow', can't be found!' but TaskBarCtrl is still undefined in link(..) method of the extWindow directive.
Any suggestions how to fix it?
var mod = angular.module('ui', [])
.directive('taskBar', function() {
var link = function(scope, el, attrs) {
$(el).css('display', 'block');
$(scope.titles).each(function(i,t) {
el.append('<span>' + t + '</span>')
});
};
return {
scope: {},
restrict : 'E',
controller: function($scope, $element, $attrs) {
$scope.titles = [];
this.addTitle = function(title) {
$scope.titles.push(w);
};
this.removeTitle = function(title) {
$scope.titles = jQuery.grep(function(n,i) {
return title != n;
});
}
},
link: link
};
}).directive('extWindow', function() {
return {
scope: {},
require: '^?taskBar',
restrict: 'E',
transclude: true,
template: '<div class="ui-window">\
<div class="ui-window-header"><span>{{windowTitle}}</span><div class="ui-window-close" ng-click="close()">X</div></div>\
<div class="ui-window-content" ng-transclude></div>\
</div>',
link: function(scope, element, attrs, taskBarCtrl) {
scope.windowTitle = attrs['windowTitle'];
scope.close = function() {
$(element).css('display', 'none');
}
//taskBarCtrl is not recognized!!!
taskBarCtrl.addTitle(scope.windowTitle);
}
}
});
http://jsfiddle.net/wa9fs2nm/
Thank you.
golbie.
If you have a controller for your parent directive and you need something like.
this.scope = $scope;
this.attrs = $attrs;
And in your in you link function for the child you need something like
var Ctrl = ctrl || scope.$parent.tBarCtrl;
Here's a Plunker

How would I go about adding directives to an existing directive programmatically whilst ensuring that they have access to the same model?

I have attempted the following which seems to generate the correct html, but doesn't perform the data binding i.e. the new directives that I add do not have access to the $modelValue in ngController:
.controller('MyController', ['$scope', function($scope) {
$scope.aModel = {"key": "value"}
function init() {
$scope.aModel = {"key": "value"}
}
}])
.directive('innerDirective', [function (){
return {
restrict: 'AE',
require: 'ngModel',
template: '<ul></ul>',
link: function(scope, elem, attr, ngModelController) {
console.log(ngModelController.$modelValue) // Doesnt work
}
}
}])
.directive('outerDirective', ["$log", "$compile", function($log, $compile) {
return {
restrict: 'AE',
require: 'ngModel',
scope: {},
template: '<div></div>',
link: function(scope, elem, attrs, ngModelController) {
ngModelController.$render = function() {
var aModel = ngModelController.$modelValue; // Works
var modelName = attrs['ngModel']; // aModel
var html = '<inner-directive ng-model="' + modelName + '"></inner-directive>';
var angularElement = angular.element(html);
elem.append(angularElement);
$compile(angularElement)(scope);
}
}
};
}])
HTML looks like:
<div ng-controller="MyController">
<outer-directive ng-model="aModel"></outer-directive>
</div>
This is based on reccomendations from another question: Adding ngModel to input with a directive
What is it that I'm doing wrong here?
Cheers.
There is two issue:
1- outerDirective is using isolated scope. so aModel value is undefinded in the directive scope.
2-You can't access ngModelController.$modelValue in link function immediately. Look at outerDirective that you access it in the render function.
So you can change your directives as follows:
var app = angular.module('app', []);
app.controller('MyController', ['$scope', function ($scope) {
$scope.aModel = { "key": "value" }
function init() {
$scope.aModel = { "key": "value" }
}
}]);
app.directive('innerDirective', ['$timeout', function ($timeout) {
return {
restrict: 'AE',
require: 'ngModel',
template: '<ul></ul>',
link: function (scope, elem, attr, ngModelController) {
$timeout(function () {
console.log(ngModelController.$modelValue) // It works
});
}
}
}]);
app.directive('outerDirective', ["$log", "$compile", function ($log, $compile) {
return {
restrict: 'AE',
require: 'ngModel',
template: '<div></div>',
link: function (scope, elem, attrs, ngModelController) {
ngModelController.$render = function () {
var aModel = ngModelController.$modelValue; // Works
var modelName = attrs['ngModel']; // aModel
var html = '<inner-directive ng-model="' + modelName + '"></inner-directive>';
var angularElement = angular.element(html);
elem.append(angularElement);
$compile(angularElement)(scope);
}
}
};
}]);

Resources