My app is like this:
angular.module('app', [
// other includes
'ui.bootstrap'
])
in my directive I'm working on :
angular.module('app').directive('DateFields','DatepickerController', ['$timeout', 'DatepickerController', function ($timeout, DatepickerControlle) {
return {
restrict: 'A',
replace: true,
templateUrl: 'path to calendar.html',
scope: {
element: "=",
flowParameterMap: "=?"
},
controller: ['$scope', '$element', '$timeout', function (scope, element, $timeout) {
if (!scope.element)
return;
scope.overlayClick = function (e)
{
scope.isOpen = true;
var input = $(e.currentTarget).next();
$timeout(function () {
$(input).focus();
$DatepickerController.isOpen = true;
});
}
}]
};
}]);
As you can see I'm trying from code change value of datepickers isOpen variable to show datepicker binded to the other dom object.
But all my tries end in "is undefined" error.
Try this in your directive:
scope: {
element: "=",
isOpen: "=",
flowParameterMap: "=?"
},
Now you should be able to chagne isOpen value.
Related
I am trying to watch when an array in a service is updated. I update this array in the service using a function in a directive based controller. Now for some reason the watch function does not get called in the link function of the second directive. Why is watch not being called in the second directive. I am trying to update the scope of a variable in the second directive so that it updates when the first directive function updates the service.
The Service
var productServices = angular.module('productServices', ['ngResource']);
productServices.factory('PlayerListS', [function() {
var playerList = [];
function getList() {
console.log(playerList);
return playerList;
}
function addToList(name) {
playerList.push(name);
}
return {
addToList :addToList,
getList: getList
}
}]);
The Directives
'use strict';
bands.directive("player",['PlayerListS', function (PlayerlistS) {
return {
restrict: 'E',
scope: {
person:'#person',
add:'&add'
},
replace: false,
templateUrl: "partials/player.html",
controller: function($scope, $element, $compile) {
$scope.playerList = ["A", "B"];
$scope.add = function(name) {
PlayerlistS.addToList(name);
PlayerlistS.getList();
}
},
link: function(scope, el, attrs) {
}
};
}]);
bands.directive("playerList", ['PlayerListS', function (PlayerlistS) {
return {
restrict: 'E',
replace: false,
template: "<p>Test</p>",
controller: function($scope, $element, $compile) {
},
link: function($scope, $el,$attrs) {
console.log('added');
var x = PlayerlistS.getList()
/*THIS IS WHERE THE WATCH IS HAPPENING*/
$scope.$watch('x', function (newVal, oldVal) {
console.log("CHANGED");
}, true);
}
};
}]);
The Controller
var bands = angular.module('bands', []);
bands.controller('ViewHousesCtrl', ['$scope', '$element', '$routeParams', '$q',
function ViewHousesCtrl($scope, $element, $routeParams, $q) {
$scope.playerLis = ["A","B","C"];
}]);
HTML
<player ng-show="true" person="RandomName" add="add()"></player>
<player-list ng-show="true" ng-repeat="a in playerLis"></player-list>
What your watcher is really doing, is trying to watch a variable called x on the directive scope. But your variable x is just a regular local variable, so your watcher doesn't trigger. So what your watcher basically translates to is this:
$scope.$watch(function(scope){
return scope['x'];
}, function (newVal, oldVal) {
console.log("CHANGED");
}, true);
You can probably see why it doesn't trigger. There is no variable $scope.x. Instead you should try watching the service directly, by specifying the watch function. Like this:
$scope.$watch(function(){
return PlayerlistS.getList();
}, function (newVal, oldVal) {
console.log("CHANGED");
}, true);
You have a spelling mistake in your HTML, it should be:
<player-list ng-show="true" ng-repeat="a in playerList"></player-list>
I have a template that goes something like this:
<parent-directive>
<child-directive binding="varFromParent"></child-directive>
<button ng-click="parentDirective.save()"></button>
</parent-directive>
When executing a function in the parentDirective controller, is it possible to access and manipulate the scope variables of the childDirective for e.g. if I have them set up as so
angular.module('app').directive('parentDirective', function() {
return {
restrict: 'E',
templateUrl: '...',
controllerAs: 'parentDirective',
controller: function($rootScope, $scope) {
//...
this.save = () => {
//Need to manipulate childDirective so that its
//scope.defaultValue == 'NEW DEFAULT'
}
}
}
});
and
angular.module('app').directive('childDirective', function() {
return {
restrict: 'E',
templateUrl: '...',
scope: {
binding: '='
},
controllerAs: 'childDirective',
link: function(scope, elm, attrs) {
scope.defaultValue = 'DEFAULT';
}
}
});
How would I go about doing this? Is there any way to do this without setting up a bidirectional binding? I would like to avoid a mess of attributes on the <child-directive> element if possible.
There are many way to set up a communication between your children and your parent directive:
Bidirectional binding (like you said)
Registration of your children in your parent.
You can use the directive require property and the last parameter of the link function controllers to register a children in his parent.
Events, see $scope.on/broadcast
Angular services (as they are "singletons", it's very easy to use it to share data between your directives)
etc.
Example for 2:
angular.module('Example', [])
.directive('parent', [function () {
return {
controller: function (){
// registerChildren etc
}
// ...
};
}])
.directive('children', [function () {
return {
require: ['^^parent', 'children'],
controller: function (){
// ...
}
link: function ($scope, element, attributs, controllers) {
ParentController = controllers[0];
OwnController = controllers[1];
ParentController.registerChildren(OwnController);
// ...
}
// ...
};
}])
In this case you probably don't need to isolate child's directive scope. Define a variable you need to change on parent's scope and then child's directive scope would inherit this value so you can change it value in child's directive and it would be accessible from parent.
angular.module('app').directive('parentDirective', function() {
return {
restrict: 'E',
controllerAs: 'parentCtrl',
controller: function($scope) {
$scope.value = 'Value from parent';
this.value = $scope.value
this.save = function() {
this.value = $scope.value;
}
}
}
});
angular.module('app').directive('childDirective', function() {
return {
restrict: 'E',
controllerAs: 'childCtrl',
controller: function($scope) {
$scope.value = 'Value from child';
this.setValue = function() {
$scope.value = 'New value from child';
}
}
}
});
Here is the fiddle
http://jsfiddle.net/dmitriy_nevzorov/fy31qobe/3/
Currently, I am facing one issue related to angularjs directive. I want to send outlet object from directive1 to directive2. Both directives having same controller scope. I tried with emitting event from directive1 to controller, broadcasting that event from controller to directive2 and listening to that event on directive2. but that is not working.
Directive1:
angular.module('moduleName')
.directive('directive1', function() {
return {
restrict: 'E',
templateUrl: 'directive1.html',
scope: false,
link: function(scope) {
scope.selectOutlet = function(outlet) {
scope.order.entityId = outlet.id;
scope.navigation.currentTab = 'right';
};
}
};
Here, in directive1, scope.selectOutlet() setting outletId to scope.order.entityId. I want to move/set that line to directive2 save function.
Directive2:
angular.module('moduleName')
.directive('directive2', function(config, $rootScope, $state) {
return {
restrict: 'E',
templateUrl: 'directive2.html',
scope: false,
link: function(scope) {
scope.save = function() {
// Save functionality
// scope.order.entityId = outlet.id; This is what i want to do
};
}
};
});
});
Any help.
you can use a factory or a service. Inject that factory into your directive. Now when you are trying set the data in function written into factory. `app.factory('shared',function(){
var obj ={};
obj.setData = function(){
// call this function from directive 1.
}
return obj;
})`
So if you include this factory into your directives you will get the data in 2 directives.
I will try to make some jsfiddle or plunker. If it is not clear.
Do the following in first directive
angular.module('moduleName')
.directive('directive1', function($rootScope) {
return {
restrict: 'E',
templateUrl: 'directive1.html',
scope: false,
link: function(scope) {
scope.selectOutlet = function(outlet) {
$rootScope.$broadcast('save:outlet',outlet);
//scope.order.entityId = outlet.id;
//scope.navigation.currentTab = 'right';
};
}
};
and in second
angular.module('moduleName')
.directive('directive2', function(config, $rootScope, $state) {
return {
restrict: 'E',
templateUrl: 'directive2.html',
scope: false,
link: function(scope) {
$rootScope.$on('save:outlet',function(event,data){
// do staff here
});
}
};
});
I wan't to program a flexible angular directive with it's properties defined in an own, simple object.
Angular:
contentFactory.directive("listViewDir", function ($compile) {
return {
restrict: "E",
scope: {
datasource: '=',
config: '='
},
controller: function ($scope) {
return $scope.config.controller($scope);
},
link:
return $scope.config.link(scope, element, attrs);
}
}
});
Own Configuration Object:
contentFactory.controller("indexCtrl", function ($scope) {
$scope.config = oLiftTabs;})
var configurations = [{
controller: function ($scope) {
$scope.ButtonClicked = function () {
alert('Button wurde geklickt!');
}
return $scope;
},
link: function (scope, element, attrs){
var template = "... myTemplate ..";
element.html(template);
$compile(element.contents())(scope);
},
}]
While my solution for the controller works well, it doesn't for the link.
Is there a more proper way for my approach? Can I realize access in my encapsulated method to the services (like $compile) without declaring it in the directive declaration?
Is this what you're trying to achieve? You didn't make it clear where you expect this object to live so I've assumed you want it a parent controller. This doesn't feel like a good idea but without knowing more about your use case it's hard to say.
DEMO
html
<body ng-controller="MainCtrl">
<list-view-dir config="config"></list-view-dir>
</body>
js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $compile) {
$scope.config = {
controller: function ($scope) {
$scope.ButtonClicked = function () {
alert('Button wurde geklickt!');
}
return $scope;
},
link: function (scope, element, attrs){
var template = '<button ng-click="ButtonClicked()" > Alert</button>';
element.html(template);
$compile(element.contents())(scope);
},
};
});
app.directive("listViewDir", function(){
return {
restrict: "E",
scope: {
datasource: '=',
config: '='
},
controller: function ($scope) {
return $scope.config.controller($scope);
},
link: function(scope, element, attrs){
return scope.config.link(scope, element, attrs);
}
};
});
Update
From your comments it sounds like you need to use a factory. Maybe something like this? It feels pretty ugly but it could be what you're looking for.
DEMO2
var app = angular.module('plunker', []);
app.factory('directiveConfigurations', function($compile){
var configurations = {
'listViewDir': {
controller: function ($scope) {
$scope.ButtonClicked = function(){
alert('Button wurde geklickt!');
};
return $scope;
},
link: function (scope, element, attrs){
var template = '<button ng-click="ButtonClicked()" > Alert</button>';
element.html(template);
$compile(element.contents())(scope);
}
}
};
return {
get: get
};
////////////////////////
function get(key){
return configurations[key];
}
});
app.controller('MainCtrl', function($scope, directiveConfigurations) {
$scope.config = directiveConfigurations.get('listViewDir');
});
app.directive("listViewDir", function(){
return {
restrict: "E",
scope: {
datasource: '=',
config: '='
},
controller: function ($scope) {
return $scope.config.controller($scope);
},
link: function(scope, element, attrs){
return scope.config.link(scope, element, attrs);
}
};
});
I wan to call a function which returns value and I want to use that value as ng-model.
the returned value from function should be displayed in a dialog.
I see my dialog empty - No Data.
here is my code:
my-dialog is a directive to show dialog which accepts templateurl and ng-model.
<my-dialog my-dlg-template-url="/app/ScheduleDlg.html" ng-model="ViewSchedule">
<button ng-click="openDialog()">Schedule</button>
</my-dialog>
here is the function to be called in ng-model.
$scope.ViewSchedule = function () {
console.log('ViewSchedule function call');
.....
return obj.Schedule();
};
here is the directive:
return {
require: 'ngModel',
replace: true,
transclude: false,
priority: 100,
restrict: 'E',
scope: true,
link: function ($scope, $element, $attrs, $ctrl) {
var getDialogTemplate = $attrs.myDlgTemplateUrl;
$scope.openDialog = function (confirmationAction) {
var modalInstance = $modal.open({
backdrop: 'static',
templateUrl: getDialogTemplate,
controller: "myDialogCtrl",
resolve: {
dialogData: function () {
return {
dlgData: $attrs.ngModel
};
}
}
});
modalInstance.result.then(function () {
return confirmationAction();
});
};
}
};
}])
.controller('myDialogCtrl', ['$scope', '$modal', '$modalInstance', 'dialogData', function ($scope, $modal, $modalInstance, dialogData) {
$scope.dialogData = dialogData.dlgData;
$scope.onOk = function () {
$modalInstance.close();
};
$scope.onCancel = function () {
$modalInstance.dismiss('cancel');
};
}])
Here is the dialog template :
<tr ng-repeat="item in dialogData">
<td>{{item.$index}}</td>
<td>{{item.StartDate}}</td>
<td>{{item.EndDate}}</td>
</tr>
ng-model establishes a 2 way data binding only needed if you are planning to alter the model if not a simple scope definition with one way binding or a reference bound would do it
you currently have
scope:true
you can do
scope:{
watchfor:'#result'
}
and inside the directive set a watcher
scope.$watch('watchfor',function(val){})
in your direcitve declaration you could have.
<my-dialog my-dlg-template-url="/app/ScheduleDlg.html" result="ViewSchedule()"> </my-dialog>
and set this in your directive template
<button ng-click="openDialog()">Schedule</button>
unless you want it linked to your parent scope.