AngularJS - Initialize form data based on value - angularjs

I am trying to add edit functionality to my app. In one view, I have a button that brings you to the edit page.
<button ng-click="editMission(selectedMission.key)">Edit Mission</button>
The value selectedMission.key is used to determine what to initialize the edit page's form data with.
In the controller the function looks like this:
$scope.editMission = function(key){
$location.path('/edit');
}
On the edit page I have:
<div data-ng-init="editInit()">
And in my controller I have:
$scope.editInit = function(){
var query = myDataRef.orderByKey();
query.on("child_added", function(missionSnapshot){
if (missionSnapshot.key()==key){
...
}
});
}
How can I run the initialize function based on the key value from editMission. Should I use some getter/setter approach with a global key variable? I tried just placing the editInit code in editMission but the form data does not populate on view load.

Common practice is to use a service to share variables between views/controllers.
So in your case you would use the getter/setter approach as you suspected. I don't know what exactly you're trying to do, but the service in your case would look something like this:
app.factory('missionKeyService', function() {
var currentMission= {};
return {
setMissionKey: function(missionKey) {
currentMission.key = missionKey;
},
getMissionKey: function() {
return currentMission.key;
}
}
})
And in your controller1:
//include 'missionKeyService' in your controller function params
$scope.editMission = function(key) {
missionKeyService.setMissionKey(key);
$location.path('/edit');
}
And controller2:
//include 'missionKeyService' in your controller function params
$scope.editInit = function() {
var currentKey = missionKeyService.getMissionKey();
//do something with this key
...
}

Related

Getting data from a service always return the same value (not the updated) on AngularJs

i'm doing a crud like a phone list,
in a view i want to add persons to my list, and in another view i want to show that peoples,
for do that, i'm using two controllers, and a service to store my array with the persons.
to add peoples i'm using set way to pushing it to array when i click on a button and thats works fine(possible to see with console.log at salvar function in service).
My problem is, when i go to show the list with the get method after added some persons with set, the get method still returning my list like she starts (empty). how i can fix this?
angular
.module('moduloLista')
.factory('addMostrarService', addMostrarService);
function addMostrarService() {
var listacontatos = [
];
var salvar = function(obj){
listacontatos.push(obj);
};
var getLista = function(){
return listacontatos;
};
return{
salvar: function(obj){
salvar(obj);
},
getLista: function(){
return getLista();
}
}
}
^ Service Code
angular
.module('moduloLista')
.controller('testeController',testeController);
testeController.$inject = ['addMostrarService'];
function testeController(addMostrarService) {
var vm = this;
vm.dadoslista = addMostrarService.getLista();
console.log('vm.dadoslista');
}
^ controller to get the list from service.

Creating angular base service and sub services

I'm trying to create a general service for dynamic listing objects i angular and for different types of Objects I need slightly different methods for this service. So I thought it would be the best to have a base service and some sub-services. The problem is, that I need to initialize the base service with different Objects depending on sub-service.
So that what I got so far:
Base List-Service (shortened to the relevant)
App.factory('List', ['$q',
function (){
var List = function(Item, searchParams){
this.Item = Item;
this.searchParams = searchParams;
//....
this.nextPage();
};
//.....
List.prototype.nextPage = function () {
//.....
this.Item.find({
//.....
}.bind(this));
};
return List;
}]);
Sub-service of List-Service
App.factory('UserList', [
'User', 'List','$q',
function (User, List) {
UserList = function(){
var searchParams = {
// params Object
};
return new List(User, searchParams);
};
// extend base class:
UserList.prototype.updateUser = function(id){
//.....
}
//....
return UserList;
}]);
Currently just the UserList is loaded, but: Of course it loads every time a new instance, due the new operator when it's called, but I just want one instance. But leaving the new operator throw's an error that this.nextPage(); would be undefined function. Beside this it seems the extension function updateUser is not applied.
So what's the best practice to inherit from other service with passing arguments to parent service in angular?
I gotta work it.
changed sub service to this to inherit proper from base:
App.factory('UserList', [
'User', 'List','$q',
function (User, List) {
var UserList = function(){
var searchParams = {
//.....
};
List.call(this, User, searchParams);
};
// inherit from List service
UserList.prototype = Object.create(List.prototype);
UserList.prototype.updateUser = function(id) {
//.....
};
return UserList;
}
])
;

AngularJS model best practice

I have been looking at this document:
understanding-service-types
Because I am new to AngularJS I am having some problems understanding everything in there. I still don't understand the difference between a factory and a service, but I will leave that for another day.
The problem I have now, is that I created a model as a factory and now I think I may have done it wrong.
Here is my model:
commonModule.factory('optionsModel', function () {
var _options = angular.fromJson(sessionStorage.siteOptions);
var _defaults = {
rotateBackground: false,
enableMetro: true
};
if (_options) {
_defaults.rotateBackground = _options.rotateBackground;
_defaults.enableMetro = _options.enableMetro;
}
var _save = function (options) {
console.log(options);
sessionStorage.siteOptions = angular.toJson(options);
}
return {
options: _defaults,
save: _save
};
});
As you can see here, what I am doing is setting the defaults and then I check to see if we have anything in our session, if we do I then overwrite our options with the new settings.
I also have a save function which is used to save the options to the session.
Is this the best way to make this model or should I be doing it another way?
I don't think you should think about a model in the way you're doing it.
For your purpose, you can do it in a more "angular" way :
commonModule.factory('optionsModel', function () {
var factory = {
getOptions: getOptions,
saveOptions: saveOptions
}
// If you need default values, you can assign those here,
// but you can also think about adding a dependency into your factory,
// that would be bound to your default settings.
return factory;
function getOptions(){
return angular.fromJson(sessionStorage.siteOptions);
}
function saveOptions(options){
sessionStorage.siteOptions = angular.toJson(options)
}
});

Accesing javascript variable in angularjs

I am trying to accessing javascript variable and then change it in controller and then use it in route.. but it is showing the same old one.
var userEditid = 0;
app.controller("cn_newuser", function ($scope,$window) {
editUser = function (this_) {
$window.userEditid = this_.firstElementChild.value;
alert(userEditid);
//window.location.path("#/edit_user");
//$window.location.href = "#/edit_user";
}
route
.when("/edit_user", {
templateUrl: "/master/edituser/" + userEditid //userEditid should be 3 or some thing else but is showing 0
})
in abobe route userEditid should be 3 or some thing else but is showing 0
This is because the .when() is evaluated on app instantiation, when this global var (which is really not a great idea anyways) is set to 0, rather than when your controller is run. If you are trying to say, "load the template, but the template name should vary based on a particular variable," then the way you are doing it isn't going to work.
I would do 2 things here:
Save your variable in a service, so you don't play with global vars
Have a master template, which uses an ng-include, which has the template determined by that var
Variable in a service:
app.controller("cn_newuser", function ($scope,UserIdService) {
$scope.editUser = function (this_) {
UserIdService.userEditid = this_.firstElementChild.value;
$location.path('/edit_user');
}
});
also note that I changed it to use $location.path()
Master template:
.when("/edit_user", {
templateUrl: "/master/edituser.html", controller: 'EditUser'
});
EditUser controller:
app.controller("EditUser", function ($scope,UserIdService) {
$scope.userTemplate = '/master/edituser/'+UserIdService.userEditId;
});
And then edituser.html would be:
<div ng-include="userTemplate"></div>
Of course, I would ask why you would want a separate template per user, rather than a single template that is dynamically modified by Angular, but that is not what you asked.
EDITED:
Service would be something like
app.factory('UserIdService',function() {
return {
userEditId: null
}
});
As simple as that.

AngularJS: example of two-way data binding with Resource

I have a view Transaction which has two sections
a.) view-transaction
b.) add-transaction
both are tied to the following controller
function TransactionController($scope, Category, Transaction) {
$scope.categories = Category.query(function() {
console.log('all categories - ', $scope.categories.length);
});
$scope.transactions = Transaction.query();
$scope.save = function() {
var transaction = new Transaction();
transaction.name = $scope.transaction['name'];
transaction.debit = $scope.transaction['debit'];
transaction.date = $scope.transaction['date'];
transaction.amount = $scope.transaction['amount'];
transaction.category = $scope.transaction['category'].uuid;
//noinspection JSUnresolvedFunction
transaction.$save();
$scope.transactions.push(transaction);
console.log('transaction saved successfully', transaction);
}
}
, where Transaction is a service and looks as follows
angular.module('transactionServices', ['ngResource']).factory('Transaction', function($resource) {
return $resource('/users/:userId/transactions/:transactionId', {
// todo: default user for now, change it
userId: 'bd675d42-aa9b-11e2-9d27-b88d1205c810',
transactionId: '#uuid'
});
});
When i click on tab "Transaction", the route #/transactions is activated, causing it to render both sub-views a.) and b.)
The question that I have is,
- Is there a way to update the $scope.transactions whenever I add new transaction? Since it is a resource
or I will have to manually do $scope.transactions.push(transaction);
My very first answer so take it easy on me...
You can extend the Transaction resource to update the $scope.transactions for you. It would be something like:
angular.module( ..., function($resource) {
var custom_resource = $resource('/users/:userId/transactions/:transactionId', {
...
});
custom_resource.prototype.save_and_update = function (transactions) {
var self = this;
this.$save(function () {
transactions.push(self);
});
};
return custom_resource;
});
In you controller, you would then do:
function TransactionController (...) {
...
$scope.save = function () {
...
// In place of: transaction.$save(), do:
transaction.save_and_update($scope.transactions);
...
}
}
Note: You need to make sure that object you created is fully usable in $scope. I spent 30 min trying to figure why this method failed on my code and it turn out that I am generating identity code in the database. As result, all my subsequent action on added new object failed because the new object was missing the identity!!!
There is no way to update a set of models in the scope automatically. You can push it into the $scope.transactions, or you can call a method that updates $scope.transactions with fresh data from the server. In any case, you should update the $scope in the success callback of your resource save function like this:
transaction.$save({}, function() {
$scope.transactions.push(transaction);
//or
$scope.transactions = Transaction.query();
});
In your example, when you push the transaction, you cannot be sure that the model has been saved successfully yet.
Another tip: you can create the new Transaction before you save it, and update the model directly from your view:
$scope.newTransaction = new Transaction();
$scope.addTransaction = function() {
$scope.newTransaction.save( ...
}
And somewhere in your view:
<input type="text" ng-model="newTransaction.name" />
The ng-model directive ensures that the input is bound to the name property of your newTransaction model.

Resources