Pass object back from ionic model service - angularjs

I have created a factory for a modal that pulls in an array(list) and I have a ng-click where I get the index and then get the object I want to pass the object back to my controller so I can then use it.
I not sure how I will pass the object back to the controller.
This is the function in my service that fires the open() for the modal and I am passing it the model that i receive from a rest call.
function CopyModalService($ionicModal, $rootScope) {
var $scope = $rootScope.$new(),
myModalInstanceOptions = {
scope: $scope,
animation: 'slide-in-up'
};
return {
open: open
};
function open(model) {
$ionicModal.fromTemplateUrl('templates/copy-modal.html',
myModalInstanceOptions)
.then(function (modalInstance) {
$scope.model = model;
$scope.addCopyCertificate = function(index){
console.log('click', $scope.model[index]);
};
$scope.close = function () {
closeAndRemove(modalInstance);
};
return modalInstance.show(model);
});
}
This is the html in the modal so you can get the picture
<ul class="list">
<li class="item row" ng-repeat="item in model">
<span class="col col-67">{{item.installerReference}}</span>
<span class="col">
<button class="button button-calm button-calm-search ion-ios-arrow-down"
ng-click="addCopyCertificate($index)"></button>
</span>
</li>
</ul>
When I click the button in the html addCopyCertificate() it all appears fine but how do I pass that back to the controller.
In my controller I am using it like this: (which is working)
if (res.length) {
CopyModalService.open(res);
}else{
Alert.showAlert('No matching certificates');
....
}

what about $rootScope.$broadcast? something like:
function CopyModalService($ionicModal, $rootScope) {
var $scope = $rootScope.$new(),
myModalInstanceOptions = {
scope: $scope,
animation: 'slide-in-up'
};
return {
open: open
};
function open(model) {
$ionicModal.fromTemplateUrl('templates/copy-modal.html',
myModalInstanceOptions)
.then(function (modalInstance) {
$scope.model = model;
$scope.addCopyCertificate = function(index){
console.log('click', $scope.model[index]);
$rootScope.$broadcast('update-controller',$scope.model[index]);
};
$scope.close = function () {
closeAndRemove(modalInstance);
};
return modalInstance.show(model);
});
}
and then when you want to get the value ..attach the listener with $rootScope.$on('') (or better $scope.$on()) ..something like
if (res.length) {
CopyModalService.open(res);
$scope.$on('update-controller',function(event, data){
console.log(data);
});
}else{
Alert.showAlert('No matching certificates');
....
}

Related

Sharing scope data in controller

My spring mvc controller returns an object.
My scenario is:
On click of a button from one page say sample1.html load a new page say sample2.html in the form of a table.
In sample1.html with button1 and controller1--> after clicking button1-->I have the object(lets say I got it from backend) obtained in controller1.
But the same object should be used to display a table in sample2.html
How can we use this object which is in controller1 in sample2.html?
You can use a service to store the data, and inject it in your controllers. Then, when the value is updated, you can use a broadcast event to share it.
Here is a few example:
HTML view
<div ng-controller="ControllerOne">
CtrlOne <input ng-model="message">
<button ng-click="handleClick(message);">LOG</button>
</div>
<div ng-controller="ControllerTwo">
CtrlTwo <input ng-model="message">
</div>
Controllers
function ControllerOne($scope, sharedService) {
$scope.handleClick = function(msg) {
sharedService.prepForBroadcast(msg);
};
}
function ControllerTwo($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = sharedService.message;
});
}
Service
myModule.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.message = '';
sharedService.prepForBroadcast = function(msg) {
this.message = msg;
this.broadcastItem();
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
return sharedService;
});
JSFiddle demo
you can use factory to share data between controllers
<div ng-controller="CtrlOne">
<button ng-click="submit()">submit</button>
</div>
<div ng-controller="CtrlTwo">
{{obj}}
</div>
.controller('CtrlOne', function($scope, sampleFactory) {
$scope.sampleObj = {
'name': 'riz'
}; //object u get from the backend
$scope.submit = function() {
sampleFactory.setObj($scope.sampleObj);
}
})
.controller('CtrlTwo', function($scope, sampleFactory) {
$scope.obj = sampleFactory.getObj();
})
.factory('sampleFactory', function() {
var obj = {};
return {
setObj: function(_obj) {
obj = _obj;
},
getObj: function() {
return obj;
}
}
})

Modal Factory to be used in place of Confirm()

I have created an Angular Modal factory that passes a couple parameters to create dynamic modals based upon templates and options passed back. However I want to replace all of the Confirm dialogues in my app but am struggling with this.
modal factory
(function () {
var testApp= angular.module('test');
testApp.factory('myModals', ['$uibModal', function ($uibModal) {
// called from various methods within factory
function openModal(template, data, options) {
//build all of the modal options
var modalOpts = {
animation: true,
templateUrl: template,
controller: function ($scope, $uibModalInstance, alert_data) {
$scope.alert_data = alert_data;
$scope.okToProceed = function () {
$scope.goodToGo = true;
console.log("true")
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
console.log("modal cancelled")
};
},
resolve: {
alert_data: data
},
size: '480',
backdrop: 'static'
};
// extend options set in each use type function
if (options) {
angular.extend(modalOpts, modalOpts);
}
var modalInstance = $uibModal.open(modalOpts);
modalInstance.result.then(function (data) {
// always do something when close called
return data;
}, function (data) {
//always do something when dismiss called
return data
});
return modalInstance;
}
function alert(type, text, size) {
var template;
// enter in template and string being passed back to identify modal type
switch (type) {
case 'test1':
template = 'test1.popup.html';
break;
case 'test2':
template = 'test2.popup.html';
break;
}
var opts = {
//default but should be passed back
size: size || 'sm'
};
var data = {
title: type === 'success' ? "OK" : "Error",
text: text
};
return openModal(template, data, opts);
}
return {
alert: alert
}
}])
})();
template.html
<div class="modal-header">
<h3 class="modal-title"></h3>
</div>
<div class="modal-body">
<h3>{{alert_data.text}}</h3>
</div>
<div class="modal-footer">
<button class="btn btn-warning" type="button" ng-click="okToProceed()">Ok</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
example of confirm to be replaced
$scope.discardSource = function(currentIndex) {
if (confirm("Press 'OK' to confirm.")) {
$log.debug("discardDataSource currentIndex: " + currentIndex);
$log.debug($scope.model.dataSamples[currentIndex]);

Factory value not updated in model ...what I am doing wrong?

I am new to angular-js. I have two controllers (welcomeContoller,productController) and both handling the same model within the factory.
When the model getting updating by one controller(productController) it should reflect the update in another controller. (welcomeContoller)
But its not happening now.
HTML code :
<body ng-app="myApp">
<div ng-controller="welcomeContoller">
{{totalProductCnt}}
</div>
<div ng-controller="productController">
<div class="addRemoveCart">
<span class="pull-left glyphicon glyphicon-minus" ng-click="removeProduct()"></span>
<span class="pull-right glyphicon glyphicon-plus" ng-click="addProduct(1)"></span>
</div>
</div>
JS code
var myApp = angular.module("myApp", ['ui.bootstrap']);
myApp.factory("productCountFactory", function() {
return {
totalProducts:0
};
});
myApp.controller("welcomeContoller", function($scope, productCountFactory)
{
$scope.totalProductCnt = productCountFactory.totalProducts;
});
myApp.controller("productController", function($scope, productCountFactory) {
$scope.addProduct = function() {
productCountFactory.totalProducts++;
alert(productCountFactory.totalProducts);
};
$scope.removeProduct = function() {
if(productCountFactory.totalProducts >=1)
productCountFactory.totalProducts--;
alert(productCountFactory.totalProducts);
};
});
Even after the addProduct is called the totalProductCnt is displaying as zero. I want to display the value for each increment.
Plunkr Link
Put the factory object reference on scope:
myApp.controller("welcomeContoller", function($scope, productCountFactory) {
$scope.productCountFactory = productCountFactory;
});
Watch the property of the object.
{{productCountFactory.totalProducts}}
The DEMO on PLNKR.
By putting a reference on scope, on every digest cycle the watcher looks up the value of the property and updates the DOM if there is a change.
The totalProductCnt from your welcomeController isn't updated because it is assigned only once when the controller is created.
You can use several solutions to refresh the displayed value. Use a getter for your totalProducts in the factory :
myApp.factory("productCountFactory", function() {
var totalProducts = 0;
return {
getTotalProducts: function() {
return totalProducts;
},
addProduct: function() {
totalProducts++;
},
removeProduct: function() {
totalProducts--;
}
};
});
myApp.controller("welcomeContoller", function($scope, productCountFactory) {
$scope.getTotalProducts = productCountFactory.getTotalProducts;
});
myApp.controller("productController", function($scope, productCountFactory) {
$scope.addProduct = function() {
productCountFactory.addProduct();
};
$scope.removeProduct = function() {
if (productCountFactory.getTotalProducts() >= 1)
productCountFactory.removeProduct();
};
});
And update the view accordingly:
<div ng-controller="welcomeContoller">
{{getTotalProducts()}}
</div>
Plunkr Link

Display dropdown on tick of checkbox

// I have written java code to fetch data from mongo-db. What i need to do is on tick of checkbox button i have to display those data in drop-down menu using angular-js and bootstrap. Nothing is happening after doing these code.
.html page
<div ng-controller="release">
<div class="col-md-2 col-centered col-fixed">
<label for="cloneRelease" translate="release.form.cloneRelease">CloneRelease</label>
</div>
<div>
<input type="checkbox" ng-model="ticked">
<div class="dropdown-menu" ng-repeat="release in releaseName" ng-show="ticked">{{release.name}}</div>
</div>
</div>
controller.js
releaseApp.controller('release', function($scope, $location, $http, ReleaseNameService){
$scope.releaseName = [];
init();
function init(){
ReleaseNameService.getReleaseName().then(function(data){
$scope.releaseName = data;});
console.log('inside controller: '+$scope.releaseName);
}
});
service.js
releaseApp.factory('ReleaseNameService', function($http){
var releaseName = [];
var factory = {};
factory.getReleaseName = function(){
return $http.get('release/fetchAllReleaseDetails').then(function(response){
releaseName = response.data;
console.log('inside service method'+ releaseName);
return releaseName;
});
};factory;
});
It is simple, u need to bind checkbox with ng-model:
<input type="checkbox" ng-model="ticked">
If its ticked $scope.ticked return true, else return false. If true show data, if false hide it (with ng-show)
Here is an example in jsFiddle without css ofc.
http://jsfiddle.net/RLQhh/2282/
UPDATE:
recreateing case with service.
service.js
app.factory('dataService', function ($http) {
var dataObject= {
async: function () {
var promise = $http.get('data/').then(function (response) {
return response;
});
return promise;
}
};
return dataObject;
})
controller.js
$scope.dataTest = [];
$scope.ticketed = false;
var getData = function(){
dataService.async().then(function (d) {
$scope.dataTest = d.data;
});
}
getData();
html
<input type="checkbox" ng-model="ticketed">
<div ng-show="ticketed" ng-repeat="dat in dataTest">
{{dat.name}}
</div>
...this is tested case so it should work with yours
You can make a REST call to fetch the data from your java function and store it in scope.Then you can use ng-repeat to display data in dropdown.
Here is a very good article on how to do it.
http://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2015/06/29/how-to-work-with-the-bootstrap-dropdown-in-angularjs.aspx

Passing data from ionic/angular modal using separate template html file

I'm developing a simple Ionic mobile app although the answer likely lies with Angular. The app is really simple, displays a list of employees with an Add button which displays a modal, lets the user enter some details, click Save and it's persists the data to a back-end Firebase store. It has 1 controller and a simple service. Initially I had the template html for the modal inside script tags inside the index.html and it all worked fine. When I decided to structure things out and put the modal template in a separate html file, suddenly the data object assigned to ng-modal via the input boxes no longer passes any data to the event handler to save the data, instead it's always undefined. Everything else works as it should, the modal displays ok, the event handlers are calling the right functions etc. The only change is moving the input template to a separate file. I know it's likely something really simple but can't for the life of me work out why and can't find any info about it anywhere else.
Template HTML file for the modal :
<ion-list>
<h1>Add Employee</h1>
<div class="list list-inset">
<ion-item>
<label class="item item-input">
<input type="text" placeholder="Employee Name" ng-model="data.employeeName">
</label>
<label class="item item-input">
<input type="text" placeholder="Employee Age" ng-model="data.employeeAge">
</label>
</ion-item>
<button class="button button-outline button-block button-balanced"
ng-click="addEmployee(true, data)">
Save & Add Another
</button>
<button class="button button-outline button-block button-positive"
ng-click="addEmployee(false, data)">
Save
</button>
<button class="button button-outline button-block button-assertive"
ng-click="closeAddModal()">
Cancel
</button>
</ion-list>
</ion-modal-view>
addEmployee event - data parameter is now always undefined. Worked fine with embedded template :
$scope.addEmployee = function(retainModal, data) {
var employee = {employeeName:data.employeeName,
employeeAge:data.employeeAge};
employeeService.saveEmployee(employee);
if (! retainModal) {
$scope.closeAddModal();
};
data.employeeName = "";
data.employeeAge = "";
};
Based on this question and other needs I create a service that can be useful.
See this post: Ionic modal service or see in operation: CodePen
(function () {
'use strict';
var serviceId = 'appModalService';
angular.module('app').factory(serviceId, [
'$ionicModal', '$rootScope', '$q', '$injector', '$controller', appModalService
]);
function appModalService($ionicModal, $rootScope, $q, $injector, $controller) {
return {
show: show
}
function show(templateUrl, controller, parameters) {
// Grab the injector and create a new scope
var deferred = $q.defer(),
ctrlInstance,
modalScope = $rootScope.$new(),
thisScopeId = modalScope.$id;
$ionicModal.fromTemplateUrl(templateUrl, {
scope: modalScope,
animation: 'slide-in-up'
}).then(function (modal) {
modalScope.modal = modal;
modalScope.openModal = function () {
modalScope.modal.show();
};
modalScope.closeModal = function (result) {
deferred.resolve(result);
modalScope.modal.hide();
};
modalScope.$on('modal.hidden', function (thisModal) {
if (thisModal.currentScope) {
var modalScopeId = thisModal.currentScope.$id;
if (thisScopeId === modalScopeId) {
deferred.resolve(null);
_cleanup(thisModal.currentScope);
}
}
});
// Invoke the controller
var locals = { '$scope': modalScope, 'parameters': parameters };
var ctrlEval = _evalController(controller);
ctrlInstance = $controller(controller, locals);
if (ctrlEval.isControllerAs) {
ctrlInstance.openModal = modalScope.openModal;
ctrlInstance.closeModal = modalScope.closeModal;
}
modalScope.modal.show();
}, function (err) {
deferred.reject(err);
});
return deferred.promise;
}
function _cleanup(scope) {
scope.$destroy();
if (scope.modal) {
scope.modal.remove();
}
}
function _evalController(ctrlName) {
var result = {
isControllerAs: false,
controllerName: '',
propName: ''
};
var fragments = (ctrlName || '').trim().split(/\s+/);
result.isControllerAs = fragments.length === 3 && (fragments[1] || '').toLowerCase() === 'as';
if (result.isControllerAs) {
result.controllerName = fragments[0];
result.propName = fragments[2];
} else {
result.controllerName = ctrlName;
}
return result;
}
} // end
})();
Usage:
appModalService
.show('<templateUrl>', '<controllerName> or <controllerName as ..>', <parameters obj>)
.then(function(result) {
// result from modal controller: $scope.closeModal(result) or <as name here>.closeModal(result) [Only on template]
}, function(err) {
// error
});
You can use another service to centralize the configuration of all modals:
angular.module('app')
.factory('myModals', ['appModalService', function (appModalService){
var service = {
showLogin: showLogin,
showEditUser: showEditUser
};
function showLogin(userInfo){
// return promise resolved by '$scope.closeModal(data)'
// Use:
// myModals.showLogin(userParameters) // get this inject 'parameters' on 'loginModalCtrl'
// .then(function (result) {
// // result from closeModal parameter
// });
return appModalService.show('templates/modals/login.html', 'loginModalCtrl as vm', userInfo)
// or not 'as controller'
// return appModalService.show('templates/modals/login.html', 'loginModalCtrl', userInfo)
}
function showEditUser(address){
// return appModalService....
}
}]);
You need to attach your models to the scope:
$scope.data.employeeName = "";
$scope.data.employeeAge = "";
...and similar every time you reference them.

Resources