close button in bootstrap-modal - angularjs

I have a bootstrap modal. On pressing close button, the value of the array is getting changed but it shouldn't.
controller.js
$scope.open = function(){
var modalInstance = $modal.open({
animation: true,
templateUrl: 'views/view1.html',
controller: 'controller2',
resolve: {
items: function(){
return $scope.array;
}
}
});
modalInstance.result.then(function (changed_array){
$scope.array = changed_array;
},function(){
// no change
});
};
code for second controller
angular.module('storagewebApp').controller('controller2',function($scope, $modalInstance, items) {
$scope.array = items;
$scope.ok = function(){
$modalInstance.close($scope.array);
};
$scope.cancel = function(){
$modalInstance.dismiss('cancel');
};
});
view2.html
<div class="modal-header">
<h4 class="modal-title">Set threshold</h4>
</div>
<div class="modal-body">
<div class="form-group" align="left">
<div> E:</div> <input type="text" ng-model="array[0]">
<div> M:</div><input type="text" ng-model="array[1]">
<div>T:</div><input type="text" ng-model="array[2]">
<div>F: </div><input type="text" ng-model="array[3]">
<div> I:</div><input type="text" ng-model="array[4]">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" ng-click="cancel()">Close</button>
<button type="button" class="btn btn-primary" ng-click="ok()">Save</button>
</div>
</div>
The values are changed via input box but on pressing close button values should not be sent to the first controller, but on clicking close button value of changed array is passed to first controller.

This behaviour is a common AngularJS/JavaScript mistake. When you instantiate your modal controller you are passing a reference of your array. Then inside of your modal controller you manipulate that reference, even if you don't pass it back.
When you write:
$scope.array = items
What happends in memory is that $scope.array points to the same location as items. When you modify in any way $scope.array's object you are modifying items also.
As a solution you need to deep copy your initial array into the new one, in this way creating a new object and reference. AngularJS has an inbuilt function that does this: https://docs.angularjs.org/api/ng/function/angular.copy
angular.copy
See this plunkr for example: http://plnkr.co/edit/W6EYUwQ1K1YAnfnJ2r4a?p=preview

You should create a new scope for the modal window. Like this:
var modalScope = angular.extend(
$scope.$new(), {
val1ToPassToModal: $scope.originalValue1,
val2ToPassToModal: $scope.originalValue2,
});
$modal.open({
templateUrl: '…',
controller: '…',
scope: modalScope,
resolve: {
…
}
});
Of course if you don't want to pass new values to the modal window, you can write just:
scope: $scope.$new().

Related

Array not outputting in modal

I can't figure out why the content in my array isn't outputting in the modal.
I'm doing a ng-repeat. the buttons are pulling from the array, but the content inside the modal is blank. Can anyone tell me whey?
Here's a jsfiddle:
http://jsfiddle.net/8s9ss/203/
<div ng-app="app">
<div ng-controller="RecipeController">
<div ng-repeat="recipe in ChickenRecipes">
<button class="btn btn-default" ng-click="open()">{{ recipe.name }}</button> <br />
<!--MODAL WINDOW-->
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>Recipe: {{ recipe.name }}</h3>
</div>
<div class="modal-body">
Recipe Content<br />
{{ recipe.cookTime }}
{{recipe.directions}}
</div>
<div class="modal-footer">
</div>
</script>
</div>
</div>
</div>
$modal create a child scope (and default is child of $rootScope) for the modal
So what you need is something like this:
$scope.open = function (recipe) {
$scope.recipe = recipe;
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
scope: $scope,
});
};
And:
<button class="btn btn-default" ng-click="open(recipe)">{{ recipe.name }}</button> <br />
P/s: It's better to use $modal's resolve and controller option (pass the resolved data to the new controller)
You are mixing up some concepts, putting the modal template inside the ng-repeat won't do a thing. That's not how modals work.
First, remove the template from the ng-repeat and put it elsewhere.
Then, you must create a controller for your modal:
app.controller('RecipeModalController', function($scope, $modalInstance, $modal, item){
$scope.recipe = item;
console.log(item);
});
And pass the recipe you want to open as a parameter on ng-click:
$scope.open = function (recipe) {
var modalInstance = $modal.open({
controller: 'RecipeModalController',
resolve: {item: function() {return recipe} },
templateUrl: 'myModalContent.html',
});
};
I've updated the fiddle to show it: http://jsfiddle.net/8s9ss/204/

Angularjs modal dialog form not recognizing click event from Datepair

I'm using bootstrap modal with angularjs along with datepair.
http://jonthornton.github.io/Datepair.js/
I'm working on creating a single page leave request calendar where I can add leave request to the calendar via a modal dialog box. When the box pops up, you pick your date and time you'll be absent from work. I'm experiencing an issue where the datepair doesn't work when nested within the modal dialog template.
The modal dialog works in the following code, but a click doesn't seem to trigger the calendar or time popup like in the demo link provided above. Everything works fine outside of the angularjs / modal template.
var app = angular.module('myModule', ['ui.bootstrap']);
app.controller('ModalDemoCtrl', function ($scope, $uibModal, $log) {
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
});
//Please note that $modalInstance represents a modal window (instance) dependency.
//It is not the same as the $uibModal service used above.
app.controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {
$http.get('./requestType.json')
.success(function (data) {
$scope.requestTypeList = data;
});
// initialize input widgets first
$('#requestForm .time').timepicker({
'showDuration': true,
'timeFormat': 'g:ia'
});
$('#requestForm .date').datepicker({
'format': 'm/d/yyyy',
'autoclose': true
});
// initialize datepair
var requestForm = document.getElementById('requestForm');
var datepair = new Datepair(requestForm);
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
html
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<form ng-submit="submitForm()" form-autofill-fix name="form">
<p id="requestForm">
<label>Request Type</label>
<select ng-model="formData.requestType" ng-options="rt.name for rt in requestTypeList track by rt.id" required class="form-control">
<option value="">- Select Request Type</option>
</select>
<label>Start Date</label><input type="text" class="form-control date start" ng-model="formData.startDate" required/>
<label>Start Time</label> <input type="text" class="form-control time start" ng-model="formData.startTime" required/>
<label>End Time</label><input type="text" class="form-control time end" ng-model="formData.endTime" required/>
<label>End Date</label><input type="text" class="form-control date end" ng-model="formData.endDate" required/>
<ul>
<li ng-repeat="item in items">
{{ item }}
</li>
</ul>
</p>
<input type="submit" value="Add to Agenda" class="btn btn-success"/>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
Now requestTypeList works perfectly to load the select menu, but if I click the date field, nothing pops up. What might be wrong?
I think the problem is that ModalInstanceCtrl is executing before template inserted to the DOM. The first rule of angular: do not use angular do not do DOM Manipulations from controllers, services or anywhere else but from directives.
So instead of doing this
$('#requestForm .time').timepicker({
'showDuration': true,
'timeFormat': 'g:ia'
});
from modal's controller make an directive for this:
(function () {
'use strict';
angular
.module('xp-timepicker', [])
.directive('xpTimepicker', timepicker);
function timepicker() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.timepicker({
showDuration: true,
timeFormat: 'g:ia'
});
}
};
}
}());
// to use your directive in your app include it's module as dependency for your app module
angular
.module('app', ['xp-timepicker']);
Then place this directive on input fields you need:
<input type="text" ng-model="time" xp-timepicker>
I made a working plunker for you.
the z-index of bootstrap modal by default is 1050
the z-index of the date widget seems to be 1000 by default
hence the date widget will be "under" the modal.
you will have to do some css fixes if you want the date widget to be visible above the modal window

ng-model not updates inside ng-repeat

The "declineReasonId" variable is not updates. i use $parent to access parent variable inside "ng-repeat" but it still not working.
I have ng-template html:
<script type="text/ng-template" id="boxDeclineReasonPopup.html">
<div class="modal-header">
<h3 class="modal-title">Chose reason</h3>
</div>
<div class="modal-body">
<form>
<div class="form-group reasonPopupLabel">
<div ng-repeat="(key, value) in reasons" ng-if="key != 0">
<label>{{value}}</label>
<input type="radio" class="form-control" name="reason" ng-model="$parent.declineReasonId" ng-value="{{key}}">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-disabled="declineReasonId === '0'" ng-click="ok()">Submit</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
and my controller:
(function () {
function declineReasonModalController($scope, $modalInstance, appData) {
$scope.declineReasonId = '0';
$scope.reasons = appData.report_type;
$scope.ok = function () {
$modalInstance.close($scope.declineReasonId);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.$watch('declineReasonId', function () {
debugger;
});
}
declineReasonModalController.$inject = ['$scope', '$modalInstance', 'appData'];
var controllers = angular.module('app.controllers');
controllers.controller('DeclineReasonModalController', declineReasonModalController);
})();
The modal instance triggered by function:
$scope.decline = function () {
var modalInstance = $modal.open({
templateUrl: 'boxDeclineReasonPopup.html',
controller: 'DeclineReasonModalController'
});
modalInstance.result.then(function (reasonId) {
$scope.declineReasonId = reasonId;
$scope.declineConfirm();
}, function () { });
};
If i put "{{$parent.declineReasonId }}" inside ng-repeat is duplicate copy of variable. When i press radio button is change value of one of duplicated copies. Why?
The $parent is still not the modal controller's scope yet.
You can use $parent.$parent.declineReasonId to reach the scope in your specific case.
That is why the use of $parent is discouraged.
The best practice when using ng-model is to not reference something in $scope directly, like this:
$scope.model = {};
$scope.model.declineReasonId = '0';
Then change your ng-model this instead:
ng-model="model.declineReasonId"

Angular bootstrap ui modal scope binding with parent

I am having an Angular issue getting a modal scope to unbind from the parent scope. I want the scope object I pass into the modal to be separate from the corresponding scope object.
No matter how I structure the modal object the parent always mirrors it. The only solution I have found is to change the object property names, but that would be cumbersome to do for every modal in my project.
For example, I can have a $scope variable in the parent $scope.parentData.firstName and a modal variable $scope.modalData.a.b.c.firstName, and the parent will mirror the modal value.
I guess there is some parent child $scope issues here that I am not getting.
Here is a plunk illustrating the issue:
http://plnkr.co/edit/5naWXfkv7kmzFp7U2KPv?p=preview
HTML:
<div ng-controller="ModalDemoCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>I'm a modal!</h3>
</div>
<div class="modal-body">
<input ng-model="modalData.a" />
<input ng-model="modalData.b" />
<input ng-model="modalData.c" />
Selected: <b>{{ sourceData }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
<button class="btn btn-default" ng-click="open()">Open me!</button>
{{sourceData}}
<div ng-show="sourceData">Selection from a modal: {{ test }}</div>
</div>
</body>
</html>
JS:
angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal, $log) {
$scope.sourceData = {a:'abc',b:'bcd',c:'cde'};
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
data: function () {
return $scope.sourceData;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.scopeData = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
};
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
var ModalInstanceCtrl = function ($scope, $modalInstance, data) {
$scope.modalData = {};
$scope.modalData = data;
$scope.ok = function () {
$modalInstance.close($scope.modalData);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
You are passing a reference to your current object, what you want to do is use angular.copy() to pass a deep copy of the object to the modal plnkr:
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
data: function () {
return angular.copy($scope.sourceData); // deep copy
}
}
});

Angular-ui modal return value

I'm using Angular-ui modal instance and i'm trying to get the return value but for some reason the bindings is not working correctly
var openNewAlbum = function() {
var modal = $modal.open({
templateUrl :'/app/modals/NewAlbumModal.html',
controller : function($scope, $modalInstance) {
$scope.albumTitle;
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
$scope.accept = function() {
$modalInstance.close($scope.albumTitle);
}
},
keyboard: false,
backdrop: 'static'
});
return modal;
}
this is in the controller:
$scope.newAlbum = function() {
var modalInstance = ModalService.openNewAlbum();
modalInstance.result.then(function(response) {
console.log(response);
});
}
the var response that gets logged is Whatever I assign to it inside the Modal's Controller and not what gets passed in the in Input
here is the modal template:
<div style="padding:6px">
<div class="modal-body" style="font-weigth:bold;font-size:18px">
<label for="">Nombre del Album</label>
<input class="form-control" type="text" ng-model="albumTitle">
{{albumTitle}}
<br>
</div>
<button class="btn btn-danger" ng-click="cancel()" >Cancelar</button>
<button class="btn btn-primary pull-right" ng-click="accept()">Aceptar</button>
</div>
when checking {{albumTitle}} I cant see that it changes, but when I click Accept, the return value is ' ' ....... (the value that was assign to $scope.albumTitle = '';)

Resources