Using $uibModalInstance in directive - javascript

When opening a bootstrap ui modal, if you prefer to use a directive, rather than separately a templateUrl and controller, how can you then in the controller of the directive for the modal, access $uibModalInstance in order to close the modal or whatever you need to do? Also, how can we pass items without having to add it as an attribute on the template?
angular.module('myModule', ['ui.bootstrap'])
.directive('myDirective', ['$timeout', function ($timeout) {
var controllerFn = ['$scope', '$uibModal', function ($scope, $uibModal) {
$scope.names = ['Mario','Wario','Luigi'];
$scope.openModal = function () {
var modalInstance = $uibModal.open({
animation: true,
template: '<my-modal>',
size: 'lg',
resolve: {
items: function () {
return $scope.names;
}
}
});
};
}];
return {
restrict: 'E',
templateUrl: '/Folder/my-directive.html',
controller: controllerFn,
scope: {
}
};
}])
.directive('myModal', ['$timeout', function ($timeout) {
var controllerFn = ['$scope', function ($scope) {
}];
return {
restrict: 'E',
templateUrl: '/Folder/my-modal.html',
controller: controllerFn,
scope: {
}
};
}]);

I use something like that to send parameter to modal, add an element to array and give it back to directive.
// Directive who open modal
.directive('myDirective', ['$timeout', function ($timeout) {
var controllerFn = ['$scope', '$uibModal', function ($scope, $uibModal) {
// Base array
$scope.names = ['Mario','Wario','Luigi'];
$scope.openModal = function () {
// Modal instance
var modalInstance = $uibModal.open({
animation: true,
template: '<my-modal>',
size: 'lg',
controller: 'myDirectiveModalCtrl',
controllerAs: '$modalController',
resolve: {
// Provide namesInModal as service to modal controller
namesInModal: function () {
return $scope.names;
}
}
});
// When modal close, fetch parameter given
modalInstance.result.then(function (namesFromModal) {
$scope.names = namesFromModal;
}, function () {
// $log.info('Modal dismissed at: ' + new Date());
});
};
}];
return {
restrict: 'E',
templateUrl: '/Folder/my-directive.html',
controller: controllerFn,
scope: {
}
};
}])
// Modal controller
.controller('myDirectiveModalCtrl', ['$uibModalInstance','namesInModal',
function ($uibModalInstance, namesInModal) {
// Use same name set in myDirective.controllerAs
var $modalController = this;
// Get provided parameter as service
$modalController.names = namesInModal;
// Add new element
$modalController.names.push('peach');
// Return modal variable when close
$modalController.ok = function () {
$uibModalInstance.close($modalController.names);
};
$modalController.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}
]);

In the directive's link function, $uibModalInstance is available on the scope object.

Related

injecting service into directive returns undefined

I am injecting a serivce into a directive and for some instance this service returns undefined can anyone explain what I am doing wrong?
Here is a plunker of the code below. https://plnkr.co/edit/H2x2z8ZW083NndFhiBvF?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.players = ["A","B","C"];
});
app.factory('PlayerListS', [function() {
var playerList = [];
function getList() {
return playerList;
}
function addToList(name) {
playerList.push(name);
}
return {
addToList :addToList,
getList: getList
}
}]);
app.directive("player",['PlayerListS', function (PlayerListS) {
return {
restrict: 'E',
scope: {
person:'#person',
add:'&add'
},
replace: false,
templateUrl: "player.html",
controller: function($scope, $element, $compile) {
$scope.add = function(name) {
PlayerListS.addToList(name);
console.log(PlayListS.getList());
}
}
};
}]);
You have a typo in your console because of which the code is throwing an error. Change your directive the following way
app.directive("player",['PlayerListS', function (PlayerListS) {
return {
restrict: 'E',
scope: {
person:'#person',
add:'&add'
},
replace: false,
templateUrl: "player.html",
controller: function($scope, $element, $compile) {
$scope.add = function(name) {
debugger;
PlayerListS.addToList(name);
console.log(PlayerListS.getList());
}
}
};
}]);
Working Demo: https://plnkr.co/edit/HhmOYyoZAhm6vvXp3puC?p=preview

Set Directive Angular after rendering view

I want to load my Angular Directive when my class change.
I have a directive who get the route and when this directive can get a route she set on a class in a div child.
But when the div child have the class, the directive don't run.
Route directive :
angular.module('myApp').directive('index', ['$rootScope','usersEntity', '$location', '$timeout',function($rootScope,usersEntity, $location, $timeout){
return {
restrict: 'E',
templateUrl: 'index',
replace: true,
controller: function ($scope, $element, $attrs) {
$scope.user = function () {
return usersEntity;
};
$scope.location = function () {
return $location.path().replace('/', '');
};
$rootScope.$on('$locationChangeStart', function (event) {
$scope.routeMap = {
'login': 'users-log'
};
if ($scope.location().length < 1) {
$scope.route = '';
} else {
$.each($scope.routeMap, function (index, value) {
if (index == $scope.location()) {
$scope.route = value;
}
});
}
});
},
link: function() {
}
}
}]);
Thanks and sorry for my perfect English ;)

How to call another directive from directive angularjs

I want to call alertForm directive in loginForm directive. Where I want call 'alertForm' directive in 'loginForm' is highlighted as //i want to call here
alertForm directive
angular.module('myApp')
.directive('alertForm', function () {
return {
templateUrl: 'app/directives/alert/alertForm.html',
restrict: 'E',
scope: {
topic: '=topic',
description: '=description'
},
controller: function($scope) {
$scope.words = [];
this.showAlert = function() {
$scope.description.push("hello");
};
}
};
});
loginForm directive
angular.module('myApp')
.directive('loginForm', function() {
return {
templateUrl: 'app/directives/loginForm/loginForm.html',
restrict: 'E',
scope: {
successCallback: '&',
errorCallback: '&',
emailField: '='
},
link: function (scope, element, attrs) {
},
controller: function ($rootScope, $scope, authenticationService) {
$scope.loginFormData = {};
$scope.inProgress = false;
$scope.onLogin = function (form) {
if (form.$valid) {
$scope.inProgress = true;
authenticationService.loginUser('password', $scope.loginFormData).then(function () {
$scope.successCallback({formData: $scope.loginFormData});
}, function (err) {
$scope.inProgress = false;
if (err.message) {
**// i want to call here**
}
});
}
}
}
};
});
You can use require config of directive.
When a directive requires a controller, it receives that controller as
the fourth argument of its link function. Ref : Documentation
You can implement this in your code
angular.module(‘myApp')
.directive('loginForm', function() {
return {
templateUrl: 'app/directives/loginForm/loginForm.html',
restrict: 'E',
require:'alertForm',
scope: {
successCallback: '&',
errorCallback: '&',
emailField: '='
},
link: function (scope, element, attrs, alertFormCtrl) {
scope.alertFormCtrl = alertFormCtrl;
},
controller: function ($rootScope, $scope, authenticationService) {
$scope.loginFormData = {};
$scope.inProgress = false;
$scope.onLogin = function (form) {
if (form.$valid) {
$scope.inProgress = true;
authenticationService.loginUser('password', $scope.loginFormData).then(function () {
$scope.successCallback({formData: $scope.loginFormData});
}, function (err) {
$scope.inProgress = false;
if (err.message) {
// Calling showAlert function of alertFormCtrl
$scope.alertFormCtrl.showAlert();
}
});
}
}
}
};
});
Add the following line in the app/directives/loginForm/loginForm.html :
<alertForm topic="something" description = "something" ng-if="showAlert"></alertForm>
Now inside the loginForm directive's controller : // i want to call here
use
$scope.showAlert = true;
Note: you can use some variable to setup the topic and description as well inside the alertForm.

Angular unit test

I am extends bootstrap modal like this:
.directive("modal", [function(){
var controller = function($scope, $attrs, $element, $uibModal){
var defaultOptions = {
title: "Modal title",
content: "Modal body",
controller: "DefaultModalController",
templateUrl: "js/dev/shared/directives/templates/default-modal-template.html"
};
$element.on($scope.event, function(){
var userOptions = {
title: $attrs.title,
content: $attrs.content,
templateUrl: $attrs.templateUrl,
controller: $attrs.controller
};
options = angular.extend({},defaultOptions, userOptions || {});
$uibModal.open({
templateUrl: options.templateUrl,
controller: options.controller,
resolve: {
options: function () {
return options
}
}
});
});
};
return {
restrict: "A",
scope: {
event: "#"
},
controller: ["$scope", "$attrs", "$element", "$uibModal", controller]
}
}])
.controller("DefaultModalController", ["$scope", "$modalInstance", "options",
function($scope, $modalInstance, options){
$scope.modalOptions = options;
$scope.close = function(){
$modalInstance.close();
}
}]);
and my test looks like this:
descr
ibe("ModalDirective", ()=>{
var element,
compile,
scope,
controller;
beforeEach(module("app.directive"));
beforeEach(inject((_$compile_, _$rootScope_, _$controller_)=>{
compile = _$compile_;
controller = _$controller_;
scope = _$rootScope_.$new();
element = angular.element("<button modal>test</button>")
}));
it("should create default modal window", ()=>{
element = compile(element)(scope);
console.error(element.html());
expect(true).toBeTruthy();
})
});
but when compile(element)(scope) is executing I've got this error:
TypeError: 'undefined' is not an object (evaluating 'd.indexOf')
at a (https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js:179)
What should I do to fix it?
[ EDIT ]
I fixed this, the problem was in creating directive.
In directive definition I have:
scope: {
event: "#"
}
and my template was <button modal>test</button> when I changed it to <button modal event='click'>test</button> problem was solved.

Modal is coming back undefined in directive

Google is giving me the error: "TypeError: Cannot read property 'open' of undefined" in response to my ui-bootstrap module. I've been using other ui-bootsrap directives fine.
Am I not declaring the modal dependency correctly?
angular.module('ireg').directive('study', function (studyFactory) {
return {
restrict:'E',
scope: {
objectid:'#objectid'
},
templateUrl: '/ireg/components/study/study.html',
link: function (scope, element, attrs, $modal) {
scope.openMilestonesDialog = function () {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/ireg/components/add-milestones/addMilestonesDialog.html',
controller: '/ireg/components/add-milestones/addMilestonesDialogController.js',
size: lg
});
};
}//end of link
}
});
angular.module('ireg').controller('addMilestonesDialogController', function ($scope, $modalInstance, studyId) {
$scope.ok = function () {
$modalInstance.close();
};
});
You should include $modal service in your directive function instead of link function:
angular.module('ireg').directive('study', function (studyFactory, $modal) {
return {
restrict:'E',
scope: {
objectid:'#objectid'
},
templateUrl: '/ireg/components/study/study.html',
link: function (scope, element, attrs) {
scope.openMilestonesDialog = function () {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/ireg/components/add-milestones/addMilestonesDialog.html',
controller: '/ireg/components/add-milestones/addMilestonesDialogController.js',
size: 'lg'
});
};
}//end of link
}
});
And yes, Alberto I.N.J. is right, you should set size attribute as string.
You should inject $model into directive itself and change lg to 'lg'
angular.module('ireg').directive('study', function (studyFactory, $modal) {
return {
restrict:'E',
scope: {
objectid:'#objectid'
},
templateUrl: '/ireg/components/study/study.html',
link: function (scope, element, attrs) {
scope.openMilestonesDialog = function () {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/ireg/components/add-milestones/addMilestonesDialog.html',
controller: '/ireg/components/add-milestones/addMilestonesDialogController.js',
size: 'lg'
});
};
}//end of link
}
});

Categories

Resources