Use ng-model in directive and controller - javascript

Is it possible to access in Directive the ng-model that is linked to the Controller?
<input type="text" ng-model="ctrl.valuelist.value" />
Controller:
ctrl.valuelist.value = 'initial value';
In directive:
function Directive($window) {
return {
restrict: 'E',
scope: {
},
controller: 'ctrl as ctrl',
link: function(scope, elt, attrs){
// something like this:
scope.valuelist.value = 'New value';
}
};
}

function Directive($window) {
return {
restrict: 'E',
scope: {
ngModel: '=' //<----- access to the model by this
},
controller: 'ctrl as ctrl',
link: function(scope, elt, attrs){
// something like this:
scope.ngModel = 'New value';
}
};
}
I'm a pleb, so be kind.

You can pass attributes to your directive by two way('=') this mean when you make change from directive will reflect in controller as well
function Directive($window) {
return {
restrict: 'E',
scope: {
list: '='
},
controller: 'ctrl as ctrl',
link: function(scope, elt, attrs){
// something like this:
scope.list.value = 'New value';
}
};
}
And you must pass valuelist to your directive example:
<directive list='valuelist'></directive>

Related

How do I pass a Child Directive's Data to a Parent Directive in AngularJS

How can I pass a child attribute directive's scope or attr value to a parent directive?
Given widget directive, with in-viewport attribute directive, I want to update the attribute inView each time the document is scrolled, and pass the updated value to the parent directive widget:
<widget in-viewport></widget>
In Viewport directive: passed in as an attribute of parent directive "widget"
angular.module('app').directive('inViewport', function() {
return {
restrict: 'A',
scope: false, // ensure scope is same as parents
link: function(scope, element, attr) {
angular.element(document).on('scroll', function() {
// I've tried binding it to attr and parent scope of "widget" directive
attr.inView = isElementInViewport(element);
scope.inView = isElementInViewport(element);
});
}
};
});
Widget Directive:
angular.module('app').directive('widget', function() {
return {
restrict: 'AE',
scope: {
inView: '='
},
transclude: false,
templateUrl: 'directives/widgets/widgets.tpl.html',
link: function(scope) {
console.log('In Viewport: ', scope.inView); // Null
Here is the way you can access parent directive variables,
angular.module('myApp', []).directive('widget', function() {
return {
restrict: 'E',
template: '<viewport in-view="variable"></viewport> <h1>{{variable}}</h1>',
link: function(scope, iAttrs) {
scope.variable = 10;
}
}
}).directive('viewport', function() {
return {
restrict: 'E',
scope: {
inView: "=",
},
template: '<button ng-click="click()">Directive</button>',
link: function(scope, iElement, iAttrs) {
scope.click = function() {
scope.inView++;
}
}
}
});
HTML
<div ng-app="myApp" ng-controller="Ctrl1">
<widget></widget>
</div>
Here is the working jsfiddle
http://jsfiddle.net/p75DS/784/
If you have any question, ask in the comment box
Here is a working fiddle using your directive structure:
http://jsfiddle.net/ADukg/9591/
Markup is like this:
<div ng-controller="MyCtrl" style="height: 1200px;">
{{name}}
<hr>
<widget in-viewport></widget>
</div>
Just scroll the window to trigger the event. Note that the parent directive has a watch just to prove that the var gets updated...
var myApp = angular.module('myApp',[]);
myApp.directive('inViewport', function($timeout) {
return {
restrict: 'A',
scope: false, // ensure scope is same as parents
link: function(scope, element, attr) {
angular.element(window).bind('scroll', function() {
console.log('Called');
$timeout(function() {
scope.inView++;
}, 0);
});
}
};
});
myApp.directive('widget', function() {
return {
restrict: 'AE',
transclude: false,
template: '<p>This is a widget</p>',
link: function(scope) {
scope.inView = 0;
console.log('In Viewport: ', scope.inView); // Null
scope.$watch('inView', function(newVal, oldVal) {
console.log('Updated by the child directive: ', scope.inView);
});
}
}
});
function MyCtrl($scope) {
$scope.name = 'Angular Directive Stuff';
}
You can expose an API on your parent directive and use isolateScope() to access it.
Here's a working fiddle.
var app = angular.module("app",[]);
app.directive("widget", function($rootScope){
return {
template: "<div>Scroll this page and widget will update. Scroll Y: {{scrollPosY}}</div>",
scope: {}, // <-- Creating isolate scope on <widget>. This is REQUIRED.
controller: ['$scope', function DirContainerController($scope) {
$scope.scrollPosY = 0;
// Creating an update function.
$scope.update = function(position) {
$scope.scrollPosY = position;
$scope.$digest();
};
}],
}
});
app.directive("inViewport", function($window, $timeout, $rootScope){
return {
restrict: 'A',
link:function(scope, element, attrs, parentCtrl){
// Get the scope. This can be any directive.
var parentScope = element.isolateScope();
angular.element(document).on('scroll', function() {
// As long as the parent directive implements an 'update()' function this will work.
parentScope.update($window.scrollY);
console.log('parentScope: ', parentScope);
});
}
}
});

How to have dynamic template in angularjs directive

I want to create a directive that be dynamic. In this directive define a template that have an input element. In fact this element ng-model must be dynamic, and use $scope.name in controller.
app.directive('helloWorld', function() {
return {
restrict: 'E',
replace: true,
scope: {
name: '#',
path:'#',
},
template: '<input\
type="text"\
name="{{name}}"\
ng-model="{{name}}"\
/>\,
link: function(scope, elem, attrs) {
},
controller:{
$scope.$watch($scope.name, function (newValue, oldValue) {
}
}
});
A working JSFiddle
Code
var app = angular.module('app',[])
app.directive('helloWorld', function() {
return {
restrict: 'E',
scope: {
name: '#',
path:'#',
},
template: '<input type="text" name="{{name}}" ng-model="name"/> {{name}}',
controller: function($scope) {
$scope.name = "initial value";
$scope.$watch('name', function (newValue, oldValue) {
console.log("newValue: ",newValue);
})
}
}
});
Firstly, your directive syntax is wrong, here is the right one:
app.directive('helloWorld', function() {
return {
restrict: 'E',
scope: {
name: '#',
path:'#',
},
template: '<input type="text" name="{{name}}" ng-model="name">',
link: function(scope, elem, attrs) {
},
controller: function($scope) {
$scope.name = 'asd';
$scope.$watch('name', function (newValue, oldValue) {
})
}
}
});
Secondly, if you are looking to have a dynamic model, you should use scope: {name: '='} as # is for one-time binding
edit
changed name="name in template to name="{{name}}"
And here is a demo

Angularjs directive

I want to have an attribute directive a bit similar to ng-model. I just want to additionally bind an input fields value to a scope variable (just in one direction input field -> scope variable). So I have just tried this directive but I can not get the directive called anyway.
script:
.directive('passivemodel', function () {
return {
restrict: "A",
scope: {
passivemodel: '='
},
link: function (scope, element, attrs) {
scope.$watch('passivemodel', function(newPassivemodel, oldPassivemodel) {
console.log("passive model", newPassivemodel);
});
}
};
})
html:
<input data-passivemodel="keyword">
Edit:
Hmmm .. based on vilo20 answer I am running into a very strange behavior.
while this code is working very well:
<input data-ng-model="keyword" data-passivemodel="keyword">
this one does not (note the value of passivemodel):
<input data-ng-model="keyword" data-passivemodel="keyword2">. Sure I have defined the variable in the controller.
Controller:
.controller('SearchController', function($scope, $routeParams, $search) {
$scope.search = new $search();
$scope.keyword = "";
$scope.keyword2 = "";
})
Edit2: here is a fiddle http://jsfiddle.net/HB7LU/12107/
try this:
.directive('passivemodel', function () {
return {
restrict: "A",
scope: {
passivemodel: '='
},
link: function (scope, element, attrs) {
console.log("passive model", scope.passivemodel);
$scope.$watch('passivemodel', function(newPassivemodel, oldPassivemodel) {
//put your logic when passivemodel changed
});
}
};
})
Hope it helps
Edit: Here is a plunker http://plnkr.co/edit/T039I02ai5rBbiTAHfzv?p=preview
Use the scope attribute:
.directive('passivemodel', function () {
return {
restrict: "A",
scope: {
"passivemodel": "="
},
link: function (scope, element, attrs) {
console.log("access passivemodel: ", scope.passivemodel);
}
};
})
Finally it was as simple as that:
.directive('modelRed', [function(){
return {
require: 'ngModel',
restrict: 'A',
scope: {},
link: function (scope, element, attrs, ngModel) {
scope.$watch(function () {
return ngModel.$modelValue;
}, function(newValue) {
scope.$parent[attrs.modelRed] = newValue;
//console.log(attrs.modelRed, newValue, scope);
});
}
}
}])
And in the html:
<p><input type="text" data-ng-model="testInput" data-model-red="redInput">{{redInput}}</p>
Of course you have to define testInput and redInput in the $scope object.

Communicate action thru directive attributes

I'm probably missing something here on the way $observe works inside directive. I have to child directive that needs to communicate thru their parent directive:
<parent>
<button>Change text</button>
<child text="child element"></child>
</parent>
app.directive('button', function() {
return {
require: '^parent',
scope: true,
restrict: 'E',
link: function(scope, element, attrs, parentCtrl) {
element.bind('click', function() {
parentCtrl.changeText();
});
},
};
});
app.directive('parent', function() {
return {
restrict: 'E',
scope: true,
controller: function($scope, $element, $attrs) {
var child = $element.find('child');
this.changeText = function() {
child.attr('text', 'new text');
};
}
};
});
app.directive('child', function() {
return {
restrict: 'E',
scope: true,
link: function(scope, element, attrs) {
attrs.$observe('text', function(text) {
element.html(text);
});
}
};
});
That code is only to illustrate an problem I have in the app i'm developing. All directive needs to have a isolated scope, so I cannot communicate with it. I made a plunker. Feel free to let me know if there's a better way to communicate to the child directive from the parent one.
Thank's a lot, as always!
I didnt understand why the parent and child has to have isolated scope but if you just want to communicate between parent and child you can use $emit and $on.
app.directive('parent', function($rootScope) {
return {
restrict: 'E',
scope: true,
controller: function($scope, $element, $attrs) {
var child = $element.find('child');
this.changeText = function() {
child.attr('text', 'new text');
};
$rootScope.$emit('FromParent', somedata);
}
};
});
app.directive('child', function($rootScope) {
return {
restrict: 'E',
scope: true,
link: function(scope, element, attrs) {
attrs.$observe('text', function(text) {
element.html(text);
});
$rootScope.$on('FromParent', function(event, somedata){
//Do something with the data
});
}
};
});

AngularJS : Interpolating attributes

Say I have the following two directives:
angular.module('foo').directive('outer', [function(){
return {
restrict: 'E',
scope: {
inner: '#',
innneParams: '#'
},
template: "<div {{inner}}{{innerParams}}></div>",
link: function(scope, elem, attrs){
console.debug("I AM IN YOUR OUTER DIRECTIVE PASSING YOUR D00DZ!")
}
}
}]);
angular.module('foo').directive('innerDir', [function(){
return {
restrict: 'EA',
scope: {
innerParam: '='
},
template: "<div>{{massagedInner}}</div>",
link: function(scope, elem, attrs){
console.debug('I AM IN YOUR INNER DIRECTIVE MASSAGING YOUR D00DS!')
scope.massagedInner = scope.innerParam + "FROM YOUR DOGE!"
}
}
}]);
And the following HTML:
<outer inner="inner-dir" my-awesome-scope-value="myAwesomeScopeValue" inner-params="inner-param='myAwesomeScopeValue'"></outer>
The outer directive console debug triggers, the inner one does not. Is there a good way for me to achieve this kind of behaviour?
Plunk: http://plnkr.co/edit/jXbtWvYvtFXCTWiIZUDW?p=preview
There are quite a few things you're doing wrong. I've made the changes that I thought are close to what you wanted it to do and you can change the code from here.
Here's a working version
And this is what script.js now looks like;
angular.module('foo', []);
angular.module('foo').controller('fooController', ['$scope', function(scope){
scope.myAwesomeScopeValue = 'O HAI THERE'
}]);
angular.module('foo').directive('outer', [function(){
return {
restrict: 'E',
scope: {
// inner: '#',
// innnerParams: '#'
innerParam: '#'
},
template: "<div inner {{inner}} {{inner-param}}></div>",
link: function (scope) {
console.log('OUTER', scope.innerParam);
}
}
}]);
angular.module('foo').directive('inner', [function(){
return {
restrict: 'A',
// scope: {
// innerParam: '='
// },
replace: false,
template: "<div>{{massagedInner}}</div>",
link: function(scope, elem, attrs){
scope.massagedInner = scope.innerParam + "FROM YOUR DOGE!"
console.log('INNER');
}
}
}]);
For brevity, I've left some of your lines commented out. I hope this helps.

Categories