Close modal dialog from the directive - angularjs

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);
};

Related

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

Angular directive and controller

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>

Send data from controller to directive

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>

Modal not working properly

I am facing a problem with the pop up modal in Angularjs. I have a button and on clicking I need to show a modal. Here is my code. When I click on Details button for first time, the modal pop up appears but when I click again.. the app.directive doesn't get called. Greatly appreciate the help. Thanks.
JS:
myApp.directive('modal', function () {
return {
template: '<div class="modal fade">' +
'<div class="modal-dialog">' +
'<div class="modal-content">' +
'<div class="modal-header">' +
'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' +
'<h4 class="modal-title">{{ title }}</h4>' +
'</div>' +
'<div class="modal-body" ng-transclude></div>' +
'</div>' +
'</div>' +
'</div>',
restrict: 'E',
transclude: true,
replace:true,
scope:true,
link: function postLink(scope, element, attrs) {
scope.title = attrs.title;
scope.$watch(attrs.visible, function(value){
if(value == true)
$(element).modal('show');
else
$(element).modal('hide');
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
}
};
});
.state("abc"){
controller:function(){
$scope.showModal = false;
$scope.toggleModal = function(){
$scope.showModal = false;
$scope.showModal = !$scope.showModal;
var aclpGuid = $stateParams.aclpGuid;
};
}
}
HTML:
<td>
<button ng-click="toggleModal()">Details</button>
<modal visible="showModal">
<label>Room Details</label>
</modal>
</td>
I guess the issue is the isolate scope which you have here scope:true inside the directive. Using this, the scope inside a directive is seperated from the scope outside. To confirm this I checked the scope variable with and without scope: true. Note the $$watchers here:
Without scope: true
With scope: true
The isolated scope has $$watchers == null. So any changes in the scope variable showDialog doesn't fire the watch event. So you might wanna use the parent scope i.e the controller's scope here.
The event fires once as when compiling the directive for the first time it attaches the $watchers to the element only once and for subsequent calls there is no relation between the outer scope to a directive's inner scope.
With that change and few others I have a working plunk.
controller:
myApp.controller('myCtrl', function($scope) {
$scope.showDialog = false;
$scope.toggleModal = function() {
$scope.showDialog = !$scope.showDialog;
};
});
Setting the showDialog to false, whenever the user closes the modal as #Mistalis suggested.
$(element).bind('hidden.bs.modal', function() {
scope.$apply(function() {
scope.$parent[attrs.visible] = false;
scope.showDialog = false;
});
});
directive:
myApp.directive('modal', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
templateUrl: 'modal-partial.html',
//scope: true,
link: function postLink(scope, element, attrs) {
scope.showModal = function(visible, elem) {
if (!elem)
elem = element;
if (visible)
$(elem).modal("show");
else
$(elem).modal("hide");
}
scope.title = attrs.title;
scope.$watch(attrs.visible, function(value) {
if (value === true)
$(element).modal('show');
else
$(element).modal('hide');
});
$(element).bind('shown.bs.modal', function() {
scope.$apply(function() {
scope.$parent[attrs.visible] = true;
});
});
$(element).bind('hidden.bs.modal', function() {
scope.$apply(function() {
scope.$parent[attrs.visible] = false;
scope.showDialog = false;
});
});
}
};
});

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;
});

Resources