AngularJS directive: scope - angularjs

I have the example below:
HTML:
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p>Result is {{result}}!</p>
<output-content data="name"></output-content>
</body>
JavaScript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.result = "no";
$scope.changeLabel = function() {
$scope.result = 'yes';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
result: '='
},
controller: 'MainCtrl'
};
});
outpuContent.html:
<div>
{{data}}
<button ng-click="changeLabel()">Change</button>
</div>
Plunker is: http://plnkr.co/edit/uzSrGcyQLeRNEIH7IXBf
I would like the result to be 'yes' when I click on the 'Change' button.
It doesn't work.
Could you please explain to me how to write the directive to do so ?
Regards.

You define variable in directive scope, but do not pass it. Just pass
"result" into directive. E.g:
<output-content data="name" result="result"></output-content>
I forked your plunkr: http://plnkr.co/edit/12FXjUsVdPXhPIQ1mlHt?p=preview
Hope it helpful.

In directive, delete scope . Now like This.. this will be work..
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
controller: 'MainCtrl'
};
});

Scope is not needed. Kindly delete the scope.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.result = "no";
$scope.changeLabel = function() {
$scope.result = 'oh yeah';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
controller: 'MainCtrl'
};
});

Related

controllerAs not working with inner directives

In below code, controllerAs not working with widget and filter directive.
Can you please help me to fix this.
I couldn't figure out where exactly I'm doing wrong. :-(
Expected output:
Widget directive should print the "From widget controller".
Filter directive should print the "From filter directive".
I reproduced the issue here, please check.
HTML:
<div ng-app="myApp">
<body-dir>
<icon-dir>
<filter-dir>
</filter-dir>
</icon-dir>
<widget-dir>
</widget-dir>
</body-dir>
</div>
JS:
var myApp = angular.module('myApp', []);
myApp.controller('filterController', function filterController($scope) {
var vm = this;
vm.test = "From filter directive";
alert("filter");
return vm;
});
myApp.controller('widgetController', ['$scope', function widgetController($scope) {
var oki = this;
oki.widget = "From widget controller";
alert("widget");
return oki;
}])
myApp.directive('bodyDir', function() {
return {
restrict: 'E',
link: function($scope) {
alert('body-dir');
}
};
});
myApp.directive('widgetDir', function() {
return {
restrict: 'E',
controller: 'widgetController',
controllerAs: 'oki',
template: "<span>{{oki.widget}}</span>",
link: function($scope) {
alert('widget-dir');
}
};
});
myApp.directive('filterDir', function() {
return {
controller: 'filterController',
controllerAs: 'vm',
restrict: 'E',
template: "<span>{{vm.test}}</span>",
link: function($scope) {
alert('filter-dir');
}
};
});
myApp.directive('iconDir', function() {
return {
restrict: 'E',
link: function($scope) {
alert('icon-dir');
}
};
});
As far as I remember, controllerAs was introduced in AngularJS v1.2 but in your jsfiddle you are using v1.0.1. That is why controllerAs is not working for widget and filter directives.

Calling a method within a controller that's within a custom directive

Been trying to figure this out for too long now. Maybe someone can shed some light:
Am experimenting with custom directives and as an exercise I'm trying to create a method within the custom directive's controller that can be called from a simple button within the view. But the method isn't being called, even though I can see the method (using console) as a property within isolated scope object. Any ideas please?
HTML:
<my-dir>
<p>My dir content</p>
<p><button ng-click="hideMe()">Hide element with isolated scope</button></p>
</my-dir>
JS:
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
You have to declare your template inside the directive using template: property or inside an external .html file using templateUrl:"path/to/template.html"
Example using template :
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
template : '<p>My dir content</p><p><button ng-click="hideMe()">Hide me</button></p>',
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
Example using templateUrl :
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
templateUrl : 'my-dir.tpls.html',
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
Template : my-dir.tpls.html
<p>My dir content</p>
<p><button ng-click="hideMe()">Hide me</button></p>
HTML:
<my-dir></my-dir>
You can try this,
Directive:
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
link: function($scope, element, attrs) {
$scope.hideMe = function() {
alert('hideMe called');
}
}
}
});
HTML:
<div ng-controller="MyCtrl">
<my-dir>
<p>My dir content</p>
<p>
<button ng-click="hideMe()">Hide element with isolated scope</button>
</p>
</my-dir>
</div>
DEMO

Can't access directive scope from within controller

I have an issue with my AngularJS code.
It seems I can't access my directive scope from my controller.
The directive
app.directive('PaginatedText', function(){
return {
restrict: 'E',
scope: {
text: '='
},
controller: 'PaginatedTextController',
templateUrl: '/frontend/views/paginated-text.html'
};
})
The controller
app.controller('PaginatedTextController', ['$scope', function($scope){
$scope.page = 1;
$scope.limit = 200;
console.log($scope, $scope.text);
}]);
The directive call
<paginated-text text="character.long_description"></paginated-text>
The template
<p>
{{text}}
<button>read more</button>
</p>
The printed console.log:
Any idea why console.log($scope.text) print undefined ?
Directive names must start with lowercase!
app.directive('paginatedText',
angular.module('app', [])
.run(function($rootScope) {
$rootScope.character = {
long_description: 'LirumLarum'
};
})
.directive('paginatedText', function() {
return {
restrict: 'E',
scope: {
text: '='
},
controller: 'PaginatedTextController',
template: '<p>{{text}}<button>read more</button></p>'
};
})
.controller('PaginatedTextController', ['$scope',
function($scope) {
$scope.page = 1;
$scope.limit = 200;
console.log($scope, $scope.text);
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<div ng-app="app">
<paginated-text text="character.long_description"></paginated-text>
</div>

AngularJS directive: scope with named controller

I have the example below.
HTML:
<body ng-controller="MainCtrl as MgtCtrl">
<p>Hello {{MgtCtrl.name}}!</p>
<p>Result is {{MgtCtrl.result}}!</p>
<output-content data="MgtCtrl.name" result="MgtCtrl.result"></output-content>
</body>
JavaScript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var MgtCtrl = this;
MgtCtrl.name = 'World';
MgtCtrl.result = "no";
MgtCtrl.changeLabel = function() {
alert('changeLabel');
MgtCtrl.result = 'yes';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
},
controller: 'MainCtrl',
controllerAs: 'MgtCtrl'
};
});
ouputContent.html:
<div>
{{data}}
<button ng-click="MgtCtrl.changeLabel()">Change</button>
</div>
Plunker is: http://plnkr.co/edit/BW8VDyCaRnRgxE8I9JJy
I would like the result to be 'yes' when I click on the 'Change' button.
It doesn't work because of the named controller.
Could you please explain to me how to write the directive to do so ?
Regards.
You never was binding the scope variables to the named controller in the directive.
You must add the attribute bindToController: true to the directive definition like this plunker:
http://plnkr.co/edit/2QdnkpeuTM6adG9KoyJT?p=preview
Directive code:
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
},
controller: 'MainCtrl',
controllerAs: 'MgtCtrl',
bindToController: true
};
});
This go to add the data and result binding to the respective directive controller.
I think in this case you don't need to specify controller in the directive.
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
}
};
});
Also html shoul be updated:
<body ng-controller="MainCtrl as MgtCtrl">
<p>Hello {{MgtCtrl.name}}!</p>
<p>Result is {{MgtCtrl.result}}!</p>
<output-content data="MgtCtrl.name" result="MgtCtrl.result" change-label="MgtCtrl.changeLabel()"></output-content>
</body>

AngularJS - set a model defined in a directives template

I have a directive defined like so:
angular.module('directives.myInput', [])
.directive('myInput', function($parse, $http, $sce){
return {
restrict: 'E',
template: '<input type="text" ng-model="searchStr" />',
controller: function($scope){
$scope.keyPressed = function(event){
$scope.showDropdown = true;
.
.
.
}
}
};
});
And then I have a button in html and directive above declared like so:
<div ng-controller="IndexCtrl">
<button ng-click="startNewLog()">Start</button>
<div ng-controller="ItemNewCtrl">
<myInput />
</div>
</div>
I want to change/initialize ng-model="searchStr" model on a button ng-click. How can I do that?
Thanks guys,
Jani
If I understand you right, first of all you need call child controller with $broadcast. Since we don't use isolate scope, we just call directive method from child controller:
[Short answer]
No isolate scope example
Demo 1 Fiddle
For isolate scope, I would map value to directive that listens on value change automatically:
Isolate scope example
Demo 2 Fiddle
[Full answer]
No isolate scope example
HTML
<div ng-controller = "IndexCtrl">
<button ng-click="startNewLog()">Start</button>
<div ng-controller="ItemNewCtrl">
<my-input></my-input>
</div>
</div>
JS
var app = angular.module('myModule', []);
app.controller('IndexCtrl', function ($scope) {
$scope.startNewLog = function(){
$scope.$broadcast('someEvent');
};
});
app.controller('ItemNewCtrl', function ($scope) {
$scope.$on('someEvent', function() {
$scope.callDirective();
});
});
app.$inject = ['$scope'];
app.directive('myInput', function(){
return {
restrict: 'E',
template: '<input type="text" ng-model="searchStr" />',
controller: function($scope){
$scope.searchStr;
$scope.keyPressed = function(event){
$scope.showDropdown = true;
}
},
link: function(scope, elm, attrs) {
scope.callDirective = function() {
scope.searchStr = 'callDirective';
};
}
};
});
Isolate scope example
HTML
<div ng-controller = "IndexCtrl">
<button ng-click="startNewLog()">Start</button>
<div ng-controller="ItemNewCtrl">
<my-input my-model='contInput'></my-input>
</div>
</div>
JS
var app = angular.module('myModule', []);
app.controller('IndexCtrl', function ($scope) {
$scope.startNewLog = function(){
$scope.$broadcast('someEvent');
};
});
app.controller('ItemNewCtrl', function ($scope) {
$scope.contInput = '';
$scope.count = 0;
$scope.$on('someEvent', function() {
$scope.contInput = 'hey mate';
});
});
app.$inject = ['$scope'];
app.directive('myInput', function(){
return {
restrict: 'E',
scope:{searchStr: '=myModel'},
template: '<input type="text" ng-model="searchStr" />',
controller: function($scope){
$scope.searchStr;
$scope.keyPressed = function(event){
$scope.showDropdown = true;
}
}
};
});

Resources