I try to pass an attribute directive to an element directive, is it possible? I tried do it as in example but it doesn't work.
for example I have element directive:
<np-form-input
np-form-input-attrs="np-my-attr-directive"
>
</np-form-input>
JS:
.directive('npFormInput', [function () {
return{
restrict: 'E',
templateUrl: '/resources/view/common/form_input',
link: function(scope, element, attr){
scope.attributes= attr.npFormInputAttrs;
}
};
}])
And then in directive HTML
<input
{{attributes}}
>
Thanks in advance.
EDIT: My solution based on Micah Williamson answer:
.run(['$templateCache', '$http', function($templateCache, $http){
$http.get('/resources/view/common/form_input').success(function(data){
$templateCache.put('/resources/view/common/form_input', data);
});
}])
.directive('npFormInput', ['$templateCache', '$compile', function ($templateCache, $compile) {
return{
restrict: 'E',
compile: function (ele, attrs) {
var tpl = $templateCache.get('/resources/view/common/form_input');
tpl = tpl.replace('{{attributes}}', attrs.npFormInputAttrs);
var tplEle = angular.element(tpl);
ele.replaceWith(tplEle);
return function (scope, element, attr) {
$compile(tplEle)(scope);
};
},
};
}])
I've done something similar to what you're trying to do but I had to inject the attributes in the compile. You would need to add the template to $templateCache first though.
.directive('npFormInput', [function ($templateCache, $compile) {
return{
restrict: 'E',
compile: function(ele, attrs) {
var tpl = $templateCache.$get('/resources/view/common/form_input');
tpl = tpl.replace('{{attributes}}', attrs.npFormInputAttrs);
var tplEle = angular.element(tpl);
ele.replaceWith(tplEle);
return function(scope, element, attr){
$compile(tplEle)($scope);
};
}
};
}])
Related
Before setting the compiled html to dynamic-html div, my dynamicHtml is working correctly. As you can see, there's a onClick function in directive.
But unfortunately, after setting compiled html to div, onClick is not called anymore.
var content = $compile(res)($scope);
$('dynamic-html').html(content);
My dynamicHTML directive looks like this:
.directive('dynamicHtml', function($compile, $timeout) {
return {
restrict: 'E',
transclude: true,
link: function($scope, $element) {
$scope.datePickers = {};
$scope.onClick = function (variable, $event) {
var currentTarget = $event.currentTarget;
$scope.$parent.$parent.highlight(variable, true, currentTarget);
};
I tried to add transclude on directive as you can see. But it's not working on this case.
Can you please guide me to solve this problem?
Check it out the following code,
angular.module("myApp", [])
.directive("compiled", function($compile){
return {
restrict: "AE",
scope: {},
link: function(scope, ele, attrs){
var compiled = $compile("<div><hello-world></hello-world></div>")(scope);
ele.replaceWith(compiled);
}
}
})
.directive("helloWorld", function(){
return {
restrict: "AE",
scope: {},
transculde: true,
link: function(scope, ele, attrs){
scope.sayhello = function(){
alert("Hello World");
}
},
template: '<button ng-click="sayhello()">Say Hello</button>'
}
})
Html
<compiled></compiled>
I am trying to dynamically load some HTML stored in a JSON file using Angular.
I am doing this by reading the JSON data into a scope and passing it to a directive that I wrote for loading HTML into the template.
Controller
.controller('testCtrl', function($scope, $http, $state){
$http.get('views/foo.json').then(function(res){
$scope.somehtml = res.data;
});
})
Directive
.directive('loadHtml', function($compile){
return {
restrict: 'AE',
scope: {
content: "#",
},
link: function(scope, element, attrs) {
scope.content = attrs.content;
element.html(scope.content).show();
$compile(element.contents())(scope);
},
template: '{{content}}'
};
})
This works!
<load-html content="hello success"></load-html>
This doesn't : (
<load-html content="{{somehtml}}"></load-html>
What am I missing here??
Found the solution myself, perhaps this helps someone:
I needed to "observe" the attribute value in the directive.
New Directive:
.directive('loadHtml', function($compile){
return {
restrict: 'AE',
scope: {},
link: function(scope, element, attrs) {
attrs.$observe('content', function(val) { /* $observing the attribute scope */
scope.content = val;
element.html(scope.content).show();
$compile(element.contents())(scope);
})
},
template: '{{content}}'
};
})
I'm trying to update values in a ng-repeat on a ng-model;
I have the current directive:
app.directive('myDirective', function () {
return {
require: 'ngModel',
restrict: 'E',
template: '<div ng-repeat="e in model"><input ng-model="e"/></div>',
scope: {
ngModel: '='
},
link: function($scope, elem, attrs, ngModelCtrl) {
$scope.$watch(function (){
return ngModelCtrl.$modelValue;
}, function (v) {
$scope.model = ngModelCtrl.$viewValue;
});
}
};
});
but it isn't updating the value as illustrated here:
http://plnkr.co/edit/E89sbXY0gUw53EmJobz0?p=preview
anybody knows what might be wrong?
http://plnkr.co/edit/2JwxNzBRQa1dzACoJIpF?p=preview
Had to replace $scope.model = ngModelCtrl.$viewValue; with scope.model = ngModelCtrl.$viewValue; and it works fine.
app.directive('myDirective', function () {
return {
require: 'ngModel',
restrict: 'E',
template: '<div ng-repeat="e in model"><input ng-model="e"/></div>',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs, ngModelCtrl) {
console.debug()
scope.$watch(function (){
return ngModelCtrl.$modelValue;
}, function (v) {
scope.model = ngModelCtrl.$viewValue;
})
}
};
});
UPDATE: I converted 'stuff' to an array of objects and now it works:
http://plnkr.co/edit/2JwxNzBRQa1dzACoJIpF?p=preview
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.stuff = [{number: 1},{number: 2},{number: 3}];
});
app.directive('myDirective', function () {
return {
require: 'ngModel',
restrict: 'E',
template: '<div ng-repeat="e in model"><input ng-model="e.number"/></div>',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs, ngModelCtrl) {
console.debug()
scope.$watch(function (){
return ngModelCtrl.$modelValue;
}, function (v) {
scope.model = ngModelCtrl.$viewValue;
console.log(scope.model)
})
}
};
});
#Kiwi ng-repeat creates a child scope and ng-model will use the property on the child scope, because ng-model binding will evaluate on the current scope. This is the reason why the json presented in the view doesn't change in your example as it was bound to a property on the child scope created by the ng-repeat directive.
Check this simple jsfiddle example I hope it will be of help to you.
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
{{ctrl.numbers | json}}
<numbers numbers="ctrl.numbers"></numbers>
</div>
</div>
angular
.module('demo', [])
.controller('DefaultController', DefaultController)
.controller('NumbersController', NumbersController)
.directive('numbers', numbers);
function DefaultController() {
var vm = this;
vm.numbers = [1, 2, 3];
}
function numbers()
{
var directive = {
restrict: 'E',
scope: {
numbers: '='
},
template: '<div ng-repeat="number in vm.numbers"><input type="number" ng-model="vm.numbers[$index]"/></div>',
bindToController: true,
controller: NumbersController,
controllerAs: 'vm'
};
return directive;
}
function NumbersController() {
var vm = this;
}
Problem:
I'm attempting to pass a value from an ng-repeat into a child-directive but when I try to access my passed variable in directive 2 I get "undefined".
Here's an illustration of what I am attempting. Basically directive 1 represents an array of widgets while directive 2 represents a single widget. I am attempting to pass an item from the ng-repeat loop into my child directive.
My Attempt:
Here's a simplified version of my directive 1 template:
<li ng-repeat="item in widgets">
<directive2 item="item"></directive2>
</li>
Here's a simplified version of directive 2:
angular.module('directive2').directive(
['$compile', '$rootScope',
function ($compile, $rootScope) {
return {
restrict: 'E',
scope: { item: '=' },
templateUrl: 'ext-modules/tile/widgetTemplate.html',
link: function (scope, element, attrs) {
console.log(scope.item); // undefined
}
};
}]);
The ng-repeat on widgets creates two items and I have verified that the data exists. The application works fine and doesn't throw an error but my console.log returns : undefined.
My Question:
How can I pass a value from a directive template's ng-repeat into a child-directive?
here's a fiddle: http://jsfiddle.net/3znEu/112/
Yet another solution proposal:
HTML:
<div ng-controller="MyCtrl">
<directive1></directive1>
</div>
JavaScript:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function ($scope) {
$scope.widgets = [
'a', 'b', 'c', 'd'
];
}])
.directive('directive1', function () {
return {
restrict: 'E',
scope: false,
template:
'<li ng-repeat="item in widgets">' +
'<directive2 item="item"></directive2>' +
'</li>'
}
})
.directive('directive2', ['$compile', '$rootScope',
function ($compile, $rootScope) {
return {
restrict: 'E',
scope: { item: '=' },
template:
'<div>elem = {{item}}</div>',
link: function (scope, element, attrs) {
console.log(scope.item);
}
}
}]);
Fiddle: http://jsfiddle.net/masa671/dfn75sp3/
It works fine when you put directive2 as directive name, not module:
http://jsfiddle.net/3znEu/113/
'use strict';
var app = angular.module('myApp', [])
.controller('myController', ['$scope', function($scope) {
$scope.greeting = 'Hello World!';
$scope.widgets = ["111","222","333"]
}]);
app.directive('directive1',
['$compile', '$rootScope',
function ($compile, $rootScope) {
return {
restrict: 'E',
scope: { item: '=' },
template: '<div>{{item}}</div>',
link: function (scope, element, attrs) {
console.log(scope.item); // undefined
}
};
}]);
I have modified your fiddler a bit http://jsfiddle.net/3znEu/115/. Few changes
1. Added a restrict to your directive.
2. Added a template to render the Items (only for testing and demo)
3. Changed items in scope from '#' to '='
angular.module("myApp").directive("directive1", function(){
return {
restrict: 'E',
scope: {
item: "="
},
template: "{{item}}"
}
});
Javascript code for directive
angular.directive('uiDatePicker', [function() {
return {
restrict: 'EA',
scope: {
ngModel: '=ngModel',
ngChange: '=ngChange'
},
templateUrl: 'complete/date-picker.tmp.html',
replace: true,
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
if(scope.ngModel !== undefined) {
scope.DatePicker = new DatePicker(new Date(scope.ngModel));
} else {
scope.DatePicker = new DatePicker();
}
scope.ngModel = scope.DatePicker.Value;
}
}
}])
Javascript code for controller
angular.controller('Main', ['$scope', function($scope) {
$scope.Change = function(value) {
console.log(value);
};
$scope.Value = 1000;
}])
Html code
<div ng-controller="Main">
<ui-date-picker ng-model="Date" ng-change="Change(Value)"></>
</div>
And my question: How to ng-change work ?. ngModel still work !