How to pass data in angular-fancy-modal? - angularjs

I am using angular-fancy-modal to display modals in my app.
This is my controller:
.controller('CategoryController', ['$scope', 'categoryService', '$fancyModal', function($scope, categoryService, $fancyModal) {
$scope.subcategories = {};
$scope.open = function() {
$fancyModal.open({
templateUrl: 'public/popupTmpl.html',
resolve: {
items: function() {
return $scope.subcategories;
}
}
});
};
}]);
The method ng-click calls method $open.
popupTmpl.html
<script type="text/ng-template" id="popupTmpl.html">
<div class="modal-header"> $$items$$
<div class="categories-list">
<span class="list-category-item">100</span>
</div>
</div>
</script>
In template: popupTmpl.html I tried to get items from resolve, but it does not work. How to pass data $scope.subcategories in template?

As far i understand from your question, It seems you need to display an variable $scope.subcategories from your parent controller CategoryController, to your Modal $fancyModal..
If i understood correct, just passing parent scope to your modal will resolve it..
$fancyModal.open({
templateUrl: 'public/popupTmpl.html',
scope: $scope,
resolve: {
items: function() {
return $scope.subcategories;
}
}
});
Using scope:$scope will pass the scope of the controller CategoryController to the Modal also. Thus, it will help you to use(pass) all the variables and functions within the CategoryController, in the fancyModal also..

Related

ui-router, factory share data

Hy,
I want to share data between 1 component (NavBar) and other 1 ctrl (Ctrl1) in ui-view with factory, but it's not work.
When i modify factory in component or ctrl, it modify only his own scope. I want to share factory between ctrl and component.
HTML :
<div ng-app="myApp">
<global-component></global-component>
</div>
Javascript :
var myApp = angular.module('myApp', [ 'ui.router']);
myApp.config(function ($stateProvider, $urlRouterProvider){
$stateProvider.state("state1", {
url: "#",
template: "<p>State 1 </p> <input type=\"text\" ng-model=\"vm.b\"/> {{vm.b}}",
controller: "Ctrl1",
controllerAs: 'vm'
});
$urlRouterProvider.otherwise(function($injector, $location) {
$injector.get('$state').go("state1");
});
});
//Global Component
myApp.component('globalComponent', {
template: 'Global controler </br> <nav-bar></nav-bar> <div ui-view></div>',
controller: "GlobalCtrl",
controllerAs: 'vm'
});
myApp.controller('GlobalCtrl',function(Data){
Data.test="test1";
});
//NavBar
myApp.component('navBar', {
template: 'NavBar <input type=\"text\" ng-model=\"vm.a\"/> {{vm.a}}',
controller: "NavBarCtrl",
controllerAs: 'vm'
});
myApp.controller('NavBarCtrl',function(Data){
var vm=this;
vm.a=Data.test;
});
myApp.controller('Ctrl1',function(Data){
var vm=this;
Data.test="titi";
vm.b=Data.test;
});
myApp.factory('Data', function(){
var data={};
data.test="";
return data;
});
The code :
https://codepen.io/anon/pen/YrdvbV?editors=1111
Thanks
Check out working solution here.
The reason why it's wasn't working in the first palce is that you have changed the reference to data in your setData method. When the reference is changed, your are not working with the same object as before so this vm.a=Data.getData(); is not bound to the same object as on initialization.
In your case, one way to resolve this is to wrap an object around your data (in the example provided, I used data.item instead of just data). Other options are to use $watch or something similar so values could be rebound to ng-model.

inject scope into angular material modal

I'm trying to open a modal using angular material and inject the scope of the parent, where my data is.
I am attempting to loosely follow the custom/advanced example here:
https://material.angularjs.org/latest/demo/dialog
I do not need the dialog to do anything once closed, so I've eliminated the Dialogcontroller, which seems to only handle 'cancel' and 'answer' upon close. (correct me if I'm wrong here)
The ultimate goal here is to have access to survey in the modal, which is an object in the scope of the parent.
My parent HTML has the review button:
<input type="button" value="Review" ng-click="vm.openReview($event)" />
which triggers the function:
(function () {
appModule
// parent controller
.controller('tenant.views.surveys.index', [
'$scope', 'abp.services.app.survey', '$filter', '$mdDialog',
function ($scope, surveyService, $filter, $mdDialog) {
var vm = this;
vm.openReview = function (ev) {
$mdDialog.show({
//controller: DialogController,// not needed
templateUrl: "/App/tenant/views/surveys/review_modal.html",
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: true
})
//.then(function (answer) {// not needed
// vm.modalStatus = 'You said the information was "' + answer + '".';
//}, function () {
// vm.modalStatus = 'You cancelled the dialog.';
//});
};
// not needed
//function DialogController($scope, $mdDialog) {
// $scope.hide = function() { $mdDialog.hide(); };
// $scope.cancel = function() { $mdDialog.cancel(); };
// $scope.answer = function(answer) { $mdDialog.hide(answer); };
//}
}
])
.
// then the modal controller
.controller('tenant.views.surveys.review', [
'$scope', 'abp.services.app.survey',
function ($scope, surveyService) {
var vmModal = this;
}
]);
})();
Now, in my modal, I have some content:
<div ng-controller="tenant.views.surveys.review as vmModal" class="md-padding dialogdemoBasicUsage" id="popupContainer" ng-cloak="">
<div ng-controller="tenant.views.surveys.review" class="md-padding dialogdemoBasicUsage" id="popupContainer" ng-cloak="">
<md-dialog aria-label="Mango (Fruit)">
<form ng-cloak>
{{vmModal.survey}}
</form>
</md-dialog>
</div>
But I think I'm missing a piece. I don't think vmModal actually contains the scope of the parent. I want access to vmModal.survey.
Do I need to / can I inject the scope directly into the modal controller?

Passing data between modal and controller

How can I make data available in a controller? I have created a really simple Plunk that should show data on the $scope in a modal. I’ll then need to update the data, and only update $scope on clicking “ok”. Clicking “cancel” will discard the changes.
But before I get to that step, I need to make the scope available to the modal. Most of the examples use two controllers. Do I need another controller as in this example: Passing Data to Twitter Bootstrap Modal in Angular? In my controller I have the following:
$scope.open = function(){
var modalInstance = $uibModal.open({
templateUrl: 'modal.html',
controller: 'ModalInstanceController',
resolve: {
users: function() {
return $scope.users;
}
}
});
};
How can I display the users in the template? The plunk is here: http://plnkr.co/edit/FuXjSwtljQtFYOtFRV18?p=preview
To be able to access scope of the controller you need to pass scope object to the modal when creating an instance of it:
$scope.open = function() {
var modalinstance = $uibModal.open({
scope: $scope,
templateUrl: 'modal.html',
resolve: {
users: function() {
return $scope.users;
}
}
})
};
This way Angular will create child scope of the controller $scope so you will be able to access items inside of modals scope:
Demo: http://plnkr.co/edit/0m9oktX2JHFmeiaDfOpO?p=preview
You can access scope in modal -
$scope.open = function(){
var modalinstance = $uibModal.open({
templateUrl: 'modal.html',
scope:$scope
})
};
you can do it with just one controller, is just that is a "dirty" solution, because both html files will share the same controller, which is potentially an issue.
the problem you are facing is that in the modal you don't have a defined scope, so the foreach (ng-repeat) you are doing is not getting any elements
you can fix it easily by changing your modal.html to
<div ng-controller="modalController"><div class="modal-header">
<h3 class="modal-title">Modal</h3>
</div>
<div class="modal-body">
<p>Existing users:</p>
<ul>
<li ng-repeat="user in users">{{user}}</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="button">Close</button>
</div>
</div>
as you see, now this modal has a controller (the same as the main window) and so will have a scope
or else just pass the scope to the modal definition adding
var modalinstance = $uibModal.open({
scope: $scope,...
is dirty, and you are "polluting" the scope, but it works :)
Here is some code from my current project it works as expected if you want to use any ng-click on the modal your function has to reside in ModalInstanceController
app.controller('dashboardCtrl', function ($scope, $rootScope, $location, $http, Data, $uibModal ) {
$scope.users = '';
$scope.open = function(){
var modalInstance = $uibModal.open({
templateUrl: 'modal.html',
controller: 'ModalInstanceController',
resolve: {
users: function() {
return $scope.users;
}
}
})
}
});
app.controller('ModalInstanceController', function ($scope, $uibModal, $uibModalInstance, users, $rootScope, $http, Data) {
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
}
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
}
$scope.users = users ;
$scope.selected = {
users: $scope.users[0]
};
});

AngularJS passing data to bootstrap modal

I think I'm missing something but cannot figure what.
Basically I'm trying to pass an object to the modal like below, but instead of getting the passed object I gets null...so I think is a problem with the scope but I'm new in Angular and need some help.
Controller
app.controller("musicViewModel", function ($scope, $http, $location, $uibModal, $log) {
$scope.selected = null;
$scope.open = function (item) {
$scope.selected = item;
$log.info('Open' + $scope.selected); // get right passes object
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: 'musicViewModel',
size: 'lg',
resolve: {
items: function () {
return $scope.selected;
}
}
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
});
View
<div class="row" ng-controller="musicViewModel">
<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">
<ul>
<li>
{{ selected }} // always gets null
</li>
</ul>
</div>
</script>
</div>
I'd suggest you to pass the scope of your own controller instead of passing same controller again, by doing that you can remove the resolve also.
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
scope: $scope, //passed current scope to the modal
size: 'lg'
});
Otherwise you need to create a new controller and assign that controller for modal while opening it.
When you use resolve, the map is injected into the given controller.
I recommend that u use a different controller to handle the modal functionality (separation of concerns).
I also recommend to use dependency injection to support minification of the code. Step 5 on the Angular tutorial wil explain this.
A simplified example of the modal controller would be.
(function () {
'use strict';
var app = angular.module('App');
app.controller('musicDetailController',
['$scope', '$uibModalInstance', 'items',
function ($scope, $uibModalInstance, items) {
$scope.items = items;
}]);
}());
You cannot pass an object directly.
I've tried all the solutions above, but wasn't really satisfied. I've solved the issue by writing a simple parser that enables you to pass both strings and objects directly to the modal, through the provided resolve function.
app.controller('ModalController', ['$uibModal', '$scope', function ($uibModal, $scope) {
// Initialize $modal
var $modal = this;
// Open component modal
$modal.open = function (component, size, data) {
// Init modal
var modalInstance = $uibModal.open({
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
component: component,
size: size || 'md',
resolve: parseResolve(data)
});
};
// Parse the resolve object
function parseResolve(data) {
if (typeof data === 'string') {
return {
data: function() {
return data;
}
}
}
else if (typeof data === 'object') {
var resolve = {};
angular.forEach(data, function(value, key) {
resolve[key] = function() {
return value;
}
})
return resolve;
}
}
}]);
When usings strings
Template:
<button ng-click="$modal.open('modalSomething', 'md', 'value'">
Click
</button>
Component:
bindings: {
resolve: '#'
}
When using objects
Template:
<button ng-click="$modal.open('modalSomething', 'md', {key1: value1, key2: value2})">
Click
</button>
Component:
bindings: {
resolve: '<'
}
I got the below code working:
this.OpenModal = function() {
var modalInstance = $uibModal.open({
url: "/name?parameter=" + $scope.Object.ParamValue,
templateUrl: 'views/module/page.html',
controller: myController
});
}

Using Modal Window inside ng-repeat

I have a ng-repeat and I am trying to add a modal that passes the same scope variable to the modal window. I am able to get the modal window to open but the scope value from ng-repeat is not showing inside the modal. Hopefully my code explains better. This is what I have so far:
<div ng-controller="CustomerController">
<div ng-repeat="customer in customers">
<button class="btn btn-default" ng-click="open()">{{ customer.name }}</button>
<!--MODAL WINDOW-->
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>The Customer Name is: {{ customer.name }}</h3>
</div>
<div class="modal-body">
This is where the Customer Details Goes<br />
{{ customer.details }}
</div>
<div class="modal-footer">
</div>
</script>
</div>
</div>
The controller:
app.controller('CustomerController', function($scope, $timeout, $modal, $log, customerServices) {
$scope.customers= customerServices.getCustomers();
// MODAL WINDOW
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
});
};
});
The above opens the modal window. However, the customer details such as {{ customer.name }} from the ng-repeat is not passed into the modal window. Have I got something wrong with the Controller?
I am trying to create this after looking at the Angular Bootrap UI example here: http://angular-ui.github.io/bootstrap/
EDIT:
Here is a jsfiddle sample: http://jsfiddle.net/Alien_time/8s9ss/3/
I've updated your fiddle and below code as well. I hope that will help.
Regards
var app = angular.module('app', ['ui.bootstrap']);
app.controller('ModalInstanceCtrl', function ($scope, $modalInstance, customer)
{
$scope.customer = customer;
});
app.controller('CustomerController', function($scope, $timeout, $modal, $log) {
$scope.customers = [
{
name: 'Ricky',
details: 'Some Details for Ricky',
},
{
name: 'Dicky',
details: 'Some Dicky Details',
},
{
name: 'Nicky',
details: 'Some Nicky Details',
}
];
// MODAL WINDOW
$scope.open = function (_customer) {
var modalInstance = $modal.open({
controller: "ModalInstanceCtrl",
templateUrl: 'myModalContent.html',
resolve: {
customer: function()
{
return _customer;
}
}
});
};
});
This is how I setup my modals for handleing items that I ng-repeat over and want to edit. I suggest setting it up to work with a different controller, because then you can use DI to inject the resolved item to the child scope.
$scope.openModal = function(item)
// This sets up some of the options I want the modal to open with
var options = {}
angular.extend(options, {
templateUrl: '/views/userItems/form.html',
controller: 'ItemEditController',
resolve: {
// I resolve a copy of the so it dont mess up the original if they cancel
item: function() { return angular.copy(item); }
}
});
$modal.open(options).result.then(function(updatedItem) {
// after the user saves the edits to the item it gets passed back in the then function
if(updatedItem) {
// this is a service i have to deal with talking to my db
modelService.editItem(updatedItem).then(function(result) {
// get the result back, error check then update the scope
if(result.reason) {
$scope.addAlert({type: 'error', title: 'Application Error', msg: result.reason});
} else {
angular.extend(vital, result);
$scope.addAlert({type: 'success', msg: 'Successfully updated Item!'});
}
});
}
});
};

Resources