I have two different module in which I have two directives. I need to pass data between these two directive. I use require property. but I get some error
Error: [$compile:ctreq] Controller 'yearSort', required by directive 'budgetSort', can't be found!
My first directive is
angular.module('movieApp.yearsort.directives', []).directive('yearSort',[function(){
return{
restrict : 'AEC',
replace : true,
transclude : true,
controller : 'YearsortController',
templateUrl : 'app/components/yearsort/yearsort.html',
};
}]);
In the YearsortController I have the code
angular.module('movieApp.yearsort.controller', []).controller('YearsortController', ['$scope','HomeFactory','$timeout','$state',function($scope,HomeFactory,$timeout,$state) {
this.sayHello = function() {
$scope.words = "my requier";
console.log( $scope.words);
};
}]);
In my second directive I have the code
angular.module('movieApp.budgetsort.directives', []).directive('budgetSort',[function(){
return{
restrict : 'AEC',
replace : true,
transclude : true,
controller : 'BudgetsortController',
templateUrl : 'app/components/budgetSort/budgetSort.html',
require : "yearSort",
link : function(scope,element, attrs, demoCtrl){
demoCtrl.sayHello();
}
};
}]);
Why don't you try using a Service/Factory? It is a good option when you need to pass data through components or directives
I've made this plunkr to explain: http://plnkr.co/edit/V7BLbOrrtNhXl1QlUKxA?p=preview
HTML:
<body ng-controller="myCtrl">
<first-directive></first-directive>
<second-directive></second-directive>
</body>
Javascript:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, dataService) {
$scope.name = 'World';
//set up the items.
angular.copy([ { name: 'test'} , { name: 'foo' } ], dataService.items);
});
app.directive('firstDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 1</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.directive('secondDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 2</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.factory('dataService', [function(){
return { items: [] };
}]);
The Demo
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, dataService) {
$scope.name = 'World';
//set up the items.
angular.copy([ { name: 'test'} , { name: 'foo' } ], dataService.items);
});
app.directive('firstDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 1</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.directive('secondDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 2</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.factory('dataService', [function(){
return { items: [] };
}]);
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<first-directive></first-directive>
<second-directive></second-directive>
</body>
Related
I have the following code, but I couldn't make to work, I want to pass a simple string to "parent" directive from "child" directive. Here is http://jsfiddle.net/fpax1hx7/
HTML:
<div ng-app=myApp>
<div ng-controller=MyCtrl>
<directive1></directive1>
</div>
</div>
JavaScript:
'use strict';
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function ($scope) { }])
.directive('directive1', function () {
return {
restrict: 'E',
scope: { stringtest: '=' },
template: '<directive2 stringtest="stringTest"></directive2>',
link: function (scope, element, attrs) {
console.log(scope.stringTest);
}
}
})
.directive('directive2', function () {
return {
restrict: 'E',
scope: { stringTest: '=' },
link: function (scope, element, attrs) {
scope.stringtest="This is a Test";
}
}
}]);
There was a typo. You are using stringtest instead of stringTest and you are not passing any model to directive1
'use strict';
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function($scope) {
console.log('from controller');
}])
.directive('directive1', function() {
return {
restrict: 'E',
scope: {
stringTest: '='
},
template: '<directive2 string-test="stringTest"></directive2>',
link: function(scope, element, attrs) {
console.log('from directive1');
console.log('string test from directive 1:' + scope.stringTest);
scope.$watch('stringTest', function(nv, ov) {
if (nv !== ov) {
console.log('string test from directive 1 after directive2 scope binded:' + scope.stringTest);
}
});
}
}
})
.directive('directive2', function() {
return {
restrict: 'E',
scope: {
stringTest: '='
},
link: {
pre: function(scope) {
scope.stringTest = "This is a Test";
},
post: function(scope, element, attrs) {
console.log('from directive2');
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app=myApp>
<div ng-controller=MyCtrl>
<directive1 string-test="sample"></directive1>
{{sample}}
</div>
</div>
I want to send that to my directive but I want that data to stay updated if the data in the controller changes.
// Controller
angular
.module('app')
.controller('IndexController', IndexController)
IndexController.$inject = [];
function IndexController() {
var vm = this;
vm.name = 'John';
newName = function() {
vm.name = 'Brian';
}
newName();
}
// Directive
angular
.module('app')
.directive('userName', userName);
userName.$inject = ['$document'];
function userName($document) {
var directive = {
restrict: 'EA',
template: '<div id="user"></div>',
replace: true,
scope: {
name: '='
},
link: function(scope, elem, attrs) {
console.log(scope.data);
}
}
return directive;
}
this is how I use the directive. the problem is that it always returns the first name and not the new name after the change in the controller.
<div ng-controller="indexController">
<user-name name="indexController.name">
</div>
thank you.
Try this, you just have to inject $scope into your Indexcontroller
angular
.module('app', [])
.controller('IndexController', function($scope) {
var vm = this;
vm.name = 'John';
vm.newName = function() {
vm.name = 'Brian';
console.log(vm.name);
}
//vm.newName();
})
.directive('userName', ['$document', function() {
var directive = {
restrict: 'E',
template: '<div id="user"></div>',
replace: true,
scope: {
name: '='
},
link: function(scope, elem, attrs) {
console.log(scope.name);
}
}
return directive;
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="IndexController as vm">
<user-name name="vm.name"></user-name>
<button ng-click="vm.newName()">Click</button>
</div>
Without using as in controller, you cannot use controller.prop inside the scope.
Inside the controlleryou need to call the method using its $scope or this.
Check the below code.
angular
.module('app', [])
.controller('IndexController', function($scope) {
$scope.name = 'John';
$scope.newName = function() {
$scope.name = 'Brian';
}
$scope.newName();
})
.directive('userName', ['$document', function() {
var directive = {
restrict: 'E',
template: '<div id="user"></div>',
replace: true,
scope: {
name: '='
},
link: function(scope, elem, attrs) {
console.log(scope.name);
}
}
return directive;
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="IndexController">
<user-name name="name"></user-name>
</div>
I'm trying to dynamically compile and append a directive with a dynamic attribute in the directive; however, I keep getting an error.
Anyone know why?
http://plnkr.co/edit/wOb9UuFwXR0dCZx2e2xg?p=preview
angular.module('plunker', [])
.controller('MainCtrl', function($scope) {
var vm = this;
vm.foo = {
bar: 'world'
};
}).directive('addEditConfig', AddEditConfig)
.directive('inputElement', InputElement);
function AddEditConfig($compile) {
var directive = {
restrict: 'E',
scope: {
edit: '#',
config: '=',
display: '=',
parentController: '='
},
template: '<div id="dynamicForm"></div>',
controllerAs: 'vm',
bindToController: true,
controller: AddEditConfigController,
link: linkFunction
}
return directive;
function linkFunction(scope, element, attr, ctrl) {
var params = [{description: 'foo', value:'bar'}, {description: 'foo', value:'bar'}, {description: 'foo', value:'bar'}, {description: 'foo', value:'bar'}];
for (var i = 0; i < params.length; i++) {
angular.element(document.getElementById('dynamicForm')).append($compile('<input-element param="' + params[i] + '"></input-element>')(scope));
}
}
};
function AddEditConfigController() {
};
function InputElement() {
var directive = {
restrict: 'E',
scope: {
param: '='
},
controllerAs: 'vm',
bindToController: true,
template: '<div class="form-group"> <div class="col-md-8"> <input id="port" name="textinput" type="text" placeholder="{{vm.param.description}}" class="form-control input-md" ng-model="vm.param.value"/> </div></div>',
controller: InputElementController,
link: linkFunction
}
return directive;
function linkFunction(scope, el, attr, ctrl) {
}
};
function InputElementController() {
var vm = this;
}
The problem (at least one of them) is in this statement :
angular.element(document.getElementById('dynamicForm')).append($compile('<input-element param="' + params[i] + '"></input-element>')(scope));
Writing this param="' + params[i] + '" generates the following DOM param="[Object Object]".
So It will never work as expected.
One way to achieve this :
angular.module('plunker', [])
.controller('MainCtrl', function($scope) {
var vm = this;
vm.foo = {
bar: 'world'
};
}).directive('addEditConfig', AddEditConfig)
.directive('inputElement', InputElement);
function AddEditConfig($compile) {
var directive = {
restrict: 'E',
scope: {
edit: '#',
config: '=',
display: '=',
parentController: '='
},
template: '<div id="dynamicForm"><input-element param="param" ng-repeat="param in vm.params"></input-element></div>',
controllerAs: 'vm',
controller: AddEditConfigController
}
return directive;
};
function AddEditConfigController() {
this.params = [{description: 'foo', value:'bar'}, {description: 'foo1', value:'bar1'}, {description: 'foo2', value:'bar2'}, {description: 'foo3', value:''}];
};
function InputElement() {
var directive = {
restrict: 'E',
scope: {
param: '='
},
template: '<div class="form-group"> <div class="col-md-8"> <input id="port" name="textinput" type="text" placeholder="{{param.description}}" class="form-control input-md" ng-model="param.value"/> </div></div>'
}
return directive;
};
http://plnkr.co/edit/KdPvJdBsRwbjNsBCIvVh?p=preview
I tried to make recursive directive like here
Angularjs: understanding a recursive directive
ng-switch options are all commented, ng-if works fine.
I don't know what is a problem.
Just inspect output of ng-switch
var module = angular.module('myapp', []);
module.controller("TreeCtrl", function($scope) {
$scope.controls = [
{
"label":"Checkbox",
"type":"checkbox"
},
{
"label":"input",
"type":"input"
},
{
"label":"Some group",
"type":"Group",
"controls":[
{
"label":"subcontrol",
"type":"input"
}
]
}
];
});
module.directive("tree", function($compile) {
return {
restrict: "E",
scope: {controls: '='},
template:
'<div ng-switch="control.type">' +
'<label>{{control.label}}</label>'+
'<div ng-switch-when="input"><input type="text" name="ctrl1"></input></div>'+
'<div ng-switch-when="checkbox"><input type="checkbox" "name="ctr2"></input></div>'+
'<div ng-repeat="subcontrol in control.controls">' +
'<tree control="subcontrol"></tree>' +
'</div>' +
'</div>',
compile: function(tElement, tAttr, transclude) {
//We are removing the contents/innerHTML from the element we are going to be applying the
//directive to and saving it to adding it below to the $compile call as the template
var contents = tElement.contents().remove();
var compiledContents;
return function(scope, iElement, iAttr) {
if(!compiledContents) {
compiledContents = $compile(contents, transclude);
}
compiledContents(scope, function(clone, scope) {
iElement.append(clone);
});
};
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<div ng-controller="TreeCtrl">
<div ng-repeat='control in controls'>
<tree control="control"></tree>
</div>
</div>
</div>
This should not be too hard a thing to do but I cannot figure out how best to do it.
I have a parent directive, like so:
directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
replace: true,
transclude: true,
template: '
<div class="editable-fieldset" ng-click="edit()">
<div ng-transclude></div>
...
</div>',
controller: ['$scope', function ($scope) {
$scope.edit = ->
$scope.editing = true
// ...
]
};
});
And a child directive:
.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
template: function (element, attrs) {
'<div>
<label>' + attrs.label + '</label>
<p>{{ model.' + attrs.field + ' }}</p>
...
</div>'
},
require: '^editableFieldset'
};
});
How can I easily access the model and editing properties of the parent directive from the child directive? In my link function I have access to the parent scope - should I use $watch to watch these properties?
Put together, what I'd like to have is:
<editable-fieldset model="myModel">
<editable-string label="Some Property" field="property"></editable-string>
<editable-string label="Some Property" field="property"></editable-string>
</editable-fieldset>
The idea is to have a set of fields displayed by default. If clicked on, they become inputs and can be edited.
Taking inspiration from this SO post, I've got a working solution here in this plunker.
I had to change quite a bit. I opted to have an isolated scope on the editableString as well because it was easier to bind in the correct values to the template. Otherwise, you are going to have to use compile or another method (like $transclude service).
Here is the result:
JS:
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl', function($scope) {
$scope.myModel = { property1: 'hello1', property2: 'hello2' }
});
myApp.directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
transclude: true,
replace: true,
template: '<div class="editable-fieldset" ng-click="edit()"><div ng-transclude></div></div>',
link: function(scope, element) {
scope.edit = function() {
scope.editing = true;
}
},
controller: ['$scope', function($scope) {
this.getModel = function() {
return $scope.model;
}
}]
};
});
myApp.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
scope: {
label: '#',
field: '#'
},
template: '<div><label>{{ label }}</label><p>{{ model[field] }}</p></div>',
require: '^editableFieldset',
link: function(scope, element, attrs, ctrl) {
scope.model = ctrl.getModel();
}
};
});
HTML:
<body ng-controller="Ctrl">
<h1>Hello Plunker!</h1>
<editable-fieldset model="myModel">
<editable-string label="Some Property1:" field="property1"></editable-string>
<editable-string label="Some Property2:" field="property2"></editable-string>
</editable-fieldset>
</body>
You can get access to parent controller by passing attribute in child directive link function
link: function (scope, element, attrs, parentCtrl) {
parentCtrl.$scope.editing = true;
}