Angular directive and controller - angularjs

I have a directive and a controller. The directive as fallows:
calcP.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
**scope.hideModal = function() {
scope.show = false;
delete $sope.types.individual;**
};
},
template: "..."
};
});
My controller:
calcP.controller('calcPCtrl', function($scope, $http, $window, emailSenderEndpoint) {
$scope.getVariantDomovoy = function () {
$scope.types.domovoy = $scope.variants.domovoy;
};
$scope.getVariantIndividual = function () {
$scope.types.individual = $scope.variants.individual;
};
...
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
});
My template:
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
I'd like to delete some $scope by adding it to a function. But the browser shows the error that it can't find the variable $scope.types.individual.
I just try to learnAangularJS by myself and still have some problems.

If you want to change a value of your controller from a directive, first you have to pass that variable to the directive with two way binding. Then you can change that value as below.
calcP.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '=',
types: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
**scope.hideModal = function() {
scope.show = false;
scope.types.individual = "";**
};
},
template: "..."
};
});
Make sure you are passing your $scope.types from the controller to the directive. Same as you pass show parameter
May be like this,
<model-dialog show="show" types="types"></model-dialog>

Related

How to communicate between directives in Angular js?

app.directive("itemsContainer", function() {
return {
restrict: "E",
controllerAs: "itc",
bindToController: true,
controller: function() {
this.showItems = false;
this.items = null;
this.loadItems = (data) => {
this.items = data;
this.showItems = true;
}
this.hideSummary = () => {
this.showItems = false;
}
},
templateURL:'itemsContainer.html'
};
});
app.directive("itemsSummary", function() {
return {
restrict: "E",
require: "^itc",
link: function(scope, element, attrs, ctrl) {
scope.showSummary = ctrl.showItems;
scope.items = ctrl.items;
},
templateURL:'itemsSummary.html'
};
});
app.directive("itemsList", function() {
return {
restrict: "E",
require: "^itc",
scope: {
items = "="
},
link: function(scope, element, attrs, ctrl) {
if(items !== null)
{
ctrl.loadItems(items);
}
scope.hideSummary = () => {
ctrl.hideSummary();
}
},
templateURL:'itemsList.html'
};
});
<itemsContainer>
<itemsSummary>{{itemsSummary}}</itemsSummary>
<itemsList>{{items}}</itemsList>
</itemsContainer>
Here, when itemsList directive set the Hide summary using itemsContainer controller, which is not updated in itemsSummary?
how to make all the three directive in sync?
Best way to communicate between sibling directive?
Currently am doing with Event emit which I don't want to do.
I need a best practice solution.
My requirement:
<parent>
<child1></child1>
<child2></child2>
</parent>
How to communicate any update in child2 to child1?
You need to do manual transclution, that's what I did in a similar situation. Anglers default transclution won't work, since it creates a new scope.
<itemsContainer>
<itemsSummarydata="$ctrl.data"></itemsSummary>
</itemsContainer>
/** * Parent component */
angular.module("app").component("itemsContainer", function() {
constructor() {
return {
restrict: 'E',
replace: true,
template: "<div transclude-extended></div>",
transclude: true,
bindToController: true,
controller: function () {
var ctrl = this;
ctrl.data = 'This is sample data.';
}
};
}
});
/** * Transclude Extended Directive */
angular.module("app").directive("transcludeExtended", function(){
constructor() {
return {
link: function ($scope, $element, $attrs, controller, $transclude) {
var innerScope = $scope.$new();
$transclude(innerScope, function (clone) {
$element.empty();
$element.append(clone);
$element.on('$destroy', function () {
innerScope.$destroy();
});
});
}
}
};
});
transcludeExtended is the manual way of doing the translation, instead of ng-transclude
Reference: https://github.com/angular/angular.js/issues/1809

Reset form when i click modal pop up close button (x) in Angularjs

I have form in modal pop up.i am using directives for opening the modal pop up
mymodule.directive('modalDialogSite', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true, // Replace with the template below
transclude: true, // we want to insert custom content inside the directive
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
if (attrs.overflow)
scope.dialogStyle.overflow = attrs.overflow;
scope.hideModal = function() {
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'><i class='fa fa-times-circle'></i></div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"// See below
};
});
If i click cancel button in modal popup i use $setpristine to reset the form but If have any validation error when i click close button (x) it calls hideModal() function so modal get closed but if i reopen the modal pop the validation error still exists in modal popup.How can i reset that form.Here My working Plnkr https://plnkr.co/edit/embFJFmautH3uRbHOWU7?p=preview
I think you have missed several things here. I have created a plunkr for this and it very much self explanatory. You can go over to it and observe that it is exactly what you need. The form inside the modal gets to its initial state when it is opened and the code is well organized in this working plunkr. Also the form is reset when you open the modal.
app.directive('modalDialogAdd', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
scope.text ={
first_name : '',
last_name: ''
};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
if (attrs.overflow)
scope.dialogStyle.overflow = attrs.overflow;
scope.hideModal = function() {
scope.show = false;
};
scope.$watch('show', function (newVal, oldVal) {
if(newVal){
var childFormController = element.find('form').eq(0).controller('form');
childFormController.$setPristine();
childFormController.$setUntouched();
}
});
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'><i class='fa fa-times-circle'></i></div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});
Here is a working plunkr PLUNKR

Close modal dialog from the directive

I have a problem and I can't understand the reason, because it works on local server, but on production doesn't.
I have a directive like this:
calcP.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '=',
types: '=',
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
console.log('scope', scope);
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function() {
scope.show = false;
delete scope.types.individual;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});
In my controller I have as fallows:
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
console.log('modalShown', $scope.modalShown);
};
In the view I have as fallows:
<modal-dialog show='modalShown' types="types">
So, as far as I see using console.log the toggleModal() doesn't work.
Can you try function hoisting?
Instead of direct function assign to $scope
//what you did
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
console.log('modalShown', $scope.modalShown);
};
try to define function separately and assign it to the $scope like
$scope.toggleModal = toggleModal;
function toggleModal () {
$scope.modalShown = !$scope.modalShown;
console.log('modalShown', $scope.modalShown);
};

Controller as with directive not working

I want to accomplish scroll-able content by clicking on Bootstrap module. Its working fine. This is following code of my directive:
'use strict';
angular.module('cbookApp')
.directive('scrollTo', scrollTo);
scrollTo.$inject = ['$anchorScroll'];
function scrollTo($anchorScroll) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.bind('click', function (event) {
event.stopPropagation();
var location = attrs.scrollTo;
if (scope.vm.isEdit || typeof scope.vm.isEdit =="undefined" ) {
$anchorScroll(location);
} else {
$anchorScroll(location+'1');
}
});
}
};
}
But only problem is i am not sure how to apply active class to current affix li. This DEMO way i found to apply class active to current li and remove from other. It was working without Controller as but once i added controller as it stopped working and give some error of scope.
var app = angular.module('app', ['directives']);
app.controller('firstController',[function(){
var vm = this;
vm.model = { value: 'dsf'};
}]);
angular.module('directives', []).directive('toggleClass', function () {
var directiveDefinitionObject = {
restrict: 'A',
template: '<span ng-click="localFunction()" ng-class="selected" ng-transclude></span>',
replace: true,
bindToController: true,
scope: {
model: '='
},
transclude: true,
link: function (scope, element, attrs) {
scope.localFunction = function () {
scope.model.value = scope.$id;
};
scope.$watch('model.value', function () {
if (scope.model.value === scope.$id) {
scope.selected = "active";
} else {
scope.selected = '';
}
});
}
};
return directiveDefinitionObject;
});
Can you please add this in your directive.
element.parent().parent().children().each(function() {
$(this).find('a').removeClass('active');
});
element.addClass('active');
http://jsfiddle.net/hngzxmda/1/
I suggest using controllerAs in your directive too
angular.module('directives', []).directive('toggleClass', function () {
var directiveDefinitionObject = {
restrict: 'A',
template: '<span ng-click="vmd.localFunction()" ng-class="selected" ng-transclude></span>',
replace: true,
bindToController: {
model: '=',
$id: '='
},
scope: {},
transclude: true,
controller: function() {
var _this = this;
this.localFunction = function () {
_this.model.value = _this.$id;
};
},
controllerAs: 'vmd'
};
return directiveDefinitionObject;
});

How do I access a controllers scope after a transclusion?

Correct me if I am wrong, but I think in the firstDirective scenario, I am unable to achieve the behavior of the secondDirective because it's creating a sibling scope; I am unable to access the template's controller's scope. I want the behavior of the secondDirective with the power of transclusion. Is there a way to achieve this? or am I attacking this problem the wrong way?
http://jsfiddle.net/3QRDt/68/
var app = angular.module('myApp', []);
app.directive('firstDirective', function(){
return {
restrict: 'EA',
replace: true,
scope: true,
transclude: true,
template: '<div id="holder" data-ng-controller="MyController">{{shouldBeOpen}}<div ng-transclude></div><button data-ng-click="close()">Close</button></div>',
link: function(scope, element) {
scope.openDirective = function() {
scope.open()
alert("Hello from Directive")
}
scope.hello ='dad'
}
};
})
.directive('secondDirective', function(){
return {
restrict: 'EA',
replace: true,
scope: true,
transclude: true,
template: '<div id="holder" data-ng-controller="MyController">{{shouldBeOpen}}<button data-ng-click="openDirective()">{{hello}} Open</button><button data-ng-click="close()">Close</button></div>',
link: function(scope, element) {
scope.openDirective = function() {
scope.open()
alert("Hello from Directive")
}
scope.hello ='dad'
}
};
});;
app.controller('MyController', ['$scope', function($scope) {
$scope.shouldBeOpen = false
$scope.close = function() {
$scope.shouldBeOpen = false
}
$scope.open = function() {
$scope.shouldBeOpen = true
alert("Hello from Controller")
}
}]);
You can use $$prevSibling to reference from the transcluded scope to the isolated scope created by the directive:
<button data-ng-click="$$prevSibling.openDirective()">{{hello}} Open</button>

Resources