How do i pass changing data into a modal? - javascript

I'm trying to pass a changing scope variable into a modal window. I'm having trouble allowing the variable to change once the modal is open. Currently I have the data being passed to a controller when the modal is opened:
scope.open = function (roomname, image) {
console.log("clicked modal");
console.log("roomName: " + roomname);
console.log("image: " + image);
scope.imageContents = image;
console.log("scope.imageContents: " + scope.imageContents);
scope.modalInstance = $modal.open({
animation: scope.animationsEnabled,
templateUrl: 'tpl/modal-template.tpl.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function () {
console.log("scope.imageContents in resolve: " + scope.imageContents);
return scope.imageContents;
},
compassHeading: function () {
console.log("scope.imageContents in resolve: " + scope.compassHeading);
return scope.compassHeading;
}
}
});
};
and my controller:
angular.module('TestApp').controller('ModalInstanceCtrl',function ($scope, $modalInstance, items, compassHeading) {
'use strict';
$scope.items = items;
$scope.selected = {
item: $scope.items
};
$scope.compassHeading = compassHeading;
});
The compass Heading variable is constantly being updated, so I am trying to get the compassHeading variable to show these changes in the modal.

You could use a service which has your variable along with other variables:
angular.module('TestApp')
.service('TestService', [function () {
return {
model: {
'compassHeading': null
}
};
}]);
And in your main controller, you could use it like:
angular.module('TestApp')
.controller('MainController', ['$scope', 'TestService', function ($scope, testService) {
$scope.model = testService.model;
...
}]);
And in your $modal controller, you could do the same:
angular.module('TestApp')
.controller('ModalInstanceCtrl', ['$scope', 'TestService', function ($scope, testService) {
$scope.model = testService.model;
}]);
Then, anytime the value of compassHeading needs to be changed, you could just change it using the normal: $scope.model.compassHeading = <some_value_here>;.
Also, the value of compassHeading, if changed outside the controllers, will also be changed inside the controllers, since the model object of the service is called by reference.

Related

Pass data from an Angular modal's controller back to the main controller

Here is the thing. I am not able to pass data from angular modal back to the controller where i need it. the codes given below.
Controller side
'use strict'
var DataMod = angular.module('Data', ["angularGrid", 'ui.bootstrap.contextMenu', 'ui.bootstrap']);
DataMod.controller('DataController', ['$scope', '$compile', '$uibModal', '$log','$rootScope', '$http', function ($scope, $compile, $uibModal,$log, $rootScope, $http, ngUtilityService) {
//user first clicks on Add button. A modal opens up. ModalInstanceCtrl is the controller used.
$scope.adduser = function () {
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl
});
//response data should be available here.
};
var ModalInstanceCtrl = function ($scope, $uibModalInstance) {
//ajax call is made is inside this controller and i get a response.
//this response is an object. i need to pass this object back to the adduser function. mentioned it above.
};
}
]);
As you can see above, there is the main controller. I have used a modal inside there which has its own controller. I make ajax call inside that modals controller and get a response back.
I want that response as a result to be available back at the adduser function so that i can work with that data. However, it seems that once the adduser function starts, it goes to the ModalInstanceCtrl and ends its execution there. It doesnt come back to the adduser function at all. I need a way to get back to the adduser function.
Can anyone let me know how to achieve this. Also how to pass the object response from ModalInstanceCtrl to the main controller inside adduser function.
It looks like you are using the Angular Bootstrap Modal, yes? First, I would set it up so that the modal controller is separated out from the main controller. Second, you are missing the promise needed to pass the response from the modal to the main controller. You can read about the return modal instance in the docs here: https://angular-ui.github.io/bootstrap/#/modal
This is the example code from the Angular Bootstrap plunkr: http://plnkr.co/edit/nGjBtMp33pFDAQ6r7Tew?p=info
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $uibModal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
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 $uibModalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});

Working with modals in angularjs

I've got this piece of code here
<div ng-repeat="item in items" class="col-sm-4 portfolio-item">
<script type="text/ng-template" id="myModalContent.html">
However, I can't access {{item}} within the script tags. Is there a way I can insert id and type from outside the div tags? Sorry for the newbie question.
Here is the code for the controller:
.controller('listCtrl', function($scope, $modal, $log, $stateParams, items) {
$scope.animationsEnabled = true;
$scope.open = function(size) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
item: function() {
return $scope.item;
}
}
});
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 $modal service used above.
.controller('ModalInstanceCtrl', function($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
items: $scope.items
};
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
})
You can't access item object in modal template because it's compiled in isolated scope child of the $rootScope, so there is not way for modal contents to inherit items.
What you want to do is to provide a base scope for the modal instance. Try this:
var modalInstance = $modal.open({
scope: $scope, // <--- use this scope as the base for new scope
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
item: function() {
return $scope.item;
}
}
});
In above snippet, modal service will create new child scope from the passed $scope, in which case modal scope will inherit prototypically items objects.

How do I get an instance of a controller that was created by AngularJS?

I have an app based on Angular which I initialize like this:
myapp.init = (function () {
'use strict';
var angularApp = angular.module('myapp', [])
.directive('homeIterationDirective', function () {
return function (scope, element, attrs) {
var isTopCard = scope.$last ? true : false;
cards.initSingleSwipe(element.get(0), function (event) {
// I want to call indexPageController.onSwiped(event) here!
}, isTopCard);
};
})
.directive('homeDirective', function () {
return function (scope, element, attrs) {
cards.initPanel(element, function (event) {
// I want to call indexPageController.onButtonPressed(event) here!
});
};
});
angularApp.factory('AjaxService', myapp.services.AjaxService);
angularApp.controller('IndexPageController', ['$scope', '$http', '$sce', 'AjaxService', myapp.pages.IndexPageController]);
}());
My controller looks like this:
myapp.pages.IndexPageController = function ($scope, $http, $sce, MyService) {
'use strict';
var somevalue = {};
this.onSwiped = function (event) {
doSomethingWith(event, somevalue);
};
this.onButtonPressed = function (event) {
doSomethingWith(event, somevalue);
};
};
In the 2 directives homeIterationDirective and homeDirective I have 2 callbacks cards.initSingleSwipe and cards.initPanel. Within these callbacks I want to call public methods of my controller but I don't have the instance available that Angular created from IndexPageController. How can I achieve this?
Use (inject) a service (and not a Controller) if you want "to call a public method" from another place, possibly from another Controller.
angularApp.controller('MyController', function ($scope, IndexPageService) {
IndexPageService.blah();
}));
Controller is intended to receive and modify a $scope (adding methods, variables..etc). The $scope can than be used inside the template (html) that use the controller itself.
If you want to call some controller code within the Angular context but in another place, then you should probably move that calling code to a service and then call the service method directly.
But if you want to call that method outside Angular context then, you can achieve that like this:
<div id="foo" ng-controller="IndexPageController">
<!-- code -->
</div>
Now, you can write something like this:
angular.element(document.getElementById("foo")).scope().blah();
I also think you should use a service for this. But if you still need to call one controller from another you can use $controller service
(function() {
var app = angular.module('myApp', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider.when("/first", {
templateUrl: 'app/view.html',
controller: 'firstCtrl'
}).when("/second", {
templateUrl: 'app/view.html',
controller: 'secondCtrl'
})
.otherwise({
redirectTo: "/first"
});
});
app.controller('firstCtrl', function ($scope) {
$scope.name = "first Controller";
$scope.nameToUpper = function () {
return $scope.name.toUpperCase();
}
});
app.controller('secondCtrl', function ($scope, $controller) {
var newScope = $scope.$new();
$controller('firstCtrl', { $scope: newScope });
$scope.name = newScope.nameToUpper() + 'from second ctrl';
});
}())
and view is
<div>
{{name}}
</div>

Updating directive based on change in service value AngularJS

I have a basic app currently that has a list of names in a sidebar nav populated from a json call to my server. When the user clicks on a name in the sidebar, it updates the nameService to the name clicked on by the user.
When the nameService gets updated, I wanted to name-data view to make another json call the the server for the correct json file based on the name that the user clicked on.
I am having difficulty updating a view based on changes in a value contained in my service. I have two controllers and a service currently in my AngularJS app as follows:
app.js
var app = angular.module("myapp", ['ui.bootstrap']);
app.directive("sideBar", ['$http', 'nameService', function($http, nameService) {
return {
restrict: 'E',
templateUrl: "views/sidebar.html",
controller: function($scope) {
$scope.updateName = function(name) {
nameService.setName(name);
};
$http.get('../data/names.json').
success(function(data, status, headers, config) {
$scope.names = data;
});
}
};
}]);
app.directive("nameData", ['$http', 'nameService', function($http, nameService) {
return {
restrict: 'E',
templateUrl: "views/name-data.html",
controller: function($scope) {
$scope.service = nameService;
var path = "../data/" + $scope.service.name + ".json";
$http.get(path).success(function(response) {
$scope.info= response.info;
});
}
};
}]);
app.service('nameService', ['$http', function($http) {
this.name = "TestName";
this.setName = function(name) {
this.name = name;
};
this.getName = function() {
return this.name;
};
}]);
How can I update the nameData view whenever the user clicks on the sidebar nav and updates the nameService.name property?
I tried putting $scope.service.name under a watch but that didn't seem to do anything.
Is there some form of angular magic I can use to dynamically make new json calls when a new user is selected from the name list contained in my side bar?
maybe angular event broadcasts?
add rootScope to service and broadcast an event on name change:
app.service('nameService', ['$http','$rootScope', function($http,$rootScope) {
this.name = "TestName";
this.setName = function(name) {
this.name = name;
$rootScope.$broadcast('nameService-nameChanged');
};
this.getName = function() {
return this.name;
};
}]);
and then bind to that event on your directive controller scope:
app.directive("nameData", ['$http', 'nameService', function($http, nameService) {
return {
restrict: 'E',
templateUrl: "views/name-data.html",
controller: function($scope) {
$scope.service = nameService;
//turned your load mechanism in to a function
$scope.loadNameData = function(){
var path = "../data/" + $scope.service.name + ".json";
$http.get(path).success(function(response) {
$scope.info= response.info;
});
}
//initial load
$scope.loadNameData();
//subscribe to broadcast event, this will call $scope.loadNameData when the 'nameService-nameChanged' event is broadcast
$scope.$on('nameService-nameChanged',$scope.loadNameData);
}
};
}]);

Angularjs How to communicate between two modals

What I am trying to do here is:
Type in the new language name and click "Add" button, the new language will be added into the existing object.
For example: the existing object: {"default": "English"}, When I type in "German", a new object is added like this: {"default": "English", "German": "German"}
Here is my PLUNKER.
Could someone help me on that? Thanks so much, I will appreciate!
I would prefer to use events. Just subscribe one piece on some event like:
$rootScope.$on('myEvent', function(event, info){
// do something
});
And another one will fire it:
scope.$broadcast('myEvent', info);
The system glitched when I was trying to save your plunkr or I don't have a permission so here the code:
var app = angular.module('plunker', ['ui.bootstrap']);
app.factory('Data', function(){
var data =
{
Language: ''
};
return {
setLanguage: function(language) {
data.Language = language;
}
}
})
var ModalDemoCtrl = function ($scope, $modal, $log) {
$scope.languages = {"sch": "Simple Chinese"};
$scope.$on('newLanguageAdded', function(e, lang){
$scope.languages[lang] = lang;
});
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
languages: function () {
return $scope.languages;
},
newLanguage: function () {
return $scope.newLanguage;
}
}
});
};
};
// 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, $modal, $modalInstance, languages, newLanguage) {
$scope.languages = languages;
$scope.ok = function () {
$modalInstance.close($scope.languages);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.openDialog = function () {
var modalInstance = $modal.open({
templateUrl: 'addNewLanguageDialog.html',
controller: AddNewLanguageCtrl,
});
}
var AddNewLanguageCtrl = function ($scope, $rootScope, $modalInstance, Data){
$scope.newValue = {text: ''};
$scope.$watch('newLanguage', function(newValue) {
if(newValue) Data.setLanguage(newValue);
});
$scope.add = function () {
alert($scope.newValue.text);
$rootScope.$broadcast('newLanguageAdded', $scope.newValue.text);
$modalInstance.close($scope.languages);
}
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
}
}
};
You can just copy this piece into plunkr instead yours.
Also change the layout:
<div class="modal-body">
<input ng-model="newValue.text">
</div>
Let me know if something doesn't work
You need to use a service, by definition singletons, and inject it in both models, adding a watch to the array in the service and updating accordingly in the scope of every model, from the values in the service.
An angular-ui way to achieve what you need would be to use these two basic methodologies found in the angular-ui documentation. See associated plunker for the answer below.
First is to use the close(result) inside the Instance Controller of the modal which updates the result promise property of the Instance Controller
Second is to use the result promise property to get the result(s) passed on to the close() method
Inside The AddNewLanguageCtrl is something like this
$scope.data = {newLanguage: ""};
$scope.add = function() {
$scope.close(data.newLanguage);
};
Inside the your addNewLanguageDialog.html script template
instead of using
<input ng-model="newLanguage">
use this
<input ng-model="data.newLanguage">
This is because whenever a modal is created, a new scope is created under the $rootScope(default) if a scope is not passed on to the options when the $modal.open() is invoked as stated in the angular-ui documentation. If you use newLanguage as the model then it won't receive any updates inside the AddNewLanguageCtrl. You can read this to get a better understanding of what I'm talking about regarding scopes
Inside the first modal ModalInstanceCtrl is something like this
$scope.newLanguages = [];
$scope.openDialog = function () {
var modalInstance = $modal.open({
templateUrl: 'addNewLanguageDialog.html',
controller: AddNewLanguageCtrl,
});
modalInstance.result.then(function(newLanguage) {
if(newLanguage)
$scope.newLanguages.push(newLanguage);
});
};
And then in your ModalDemoCtrl
$scope.languages = [];
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl
});
modalInstance.result.then(function(languages) {
$scope.languages = $scope.languages.concat(languages);
});
};

Categories

Resources