How to access a dropdown in another controller scope in angularjs - angularjs

I have a controller name is ParentController, which has a dropdown named ddlState. How to access this dropdown in another controller named CityController in Angular JS

use a factory.
Here is a sample for simple data exchange
app.factory('dataExchange', function() {
var ret = {
getData: getData,
setData: setData
};
var data = {};
return ret;
function getData() {
return data;
}
function setData(x) {
data = x;
}
});
Simply give your object to setData in your parent controller, and get it back in your child with getData

You have different ways to work with this,
1. It is always better to have the drop downs through a directive.then you can use the same directive for multiple drop down in multiple controllers by using $on function.
2. Else if you want to write and repeat the drop down code in all html and controllers, you can go with local storage system, So once call the API result and store in local storage (browser level), in other controllers also with out calling the API you can append the data into drop down from local storage.
Other way is keep the drop down values in a $rootScope variable,and you can use in where ever you want. (but this way is not recommended)

Related

Hold data between pages in angular js

I am new to angular js.Please suggest which one is better . I have a page where I can select a no of check boxes and navigate to 2 nd page.I want to show the checked values when I press back button in browser.
Which one is better using $rootScope or stateparam or localstorage.Please consider performance also.
Going through your options one by one:
$rootScope: You should try to avoid using this option as it is associated to the global state. Use this option only if you want the data you set to be globally available throughout the app and do not want to reuse the same variable names anywhere else.
$stateParams: These typically go into the state URI as a dynamic part of the whole URL. This has only limited usage, and may not be a good idea for your use case where you need to store data from multiple checkboxes.
localStorage: This is slower than using a JavaScript variable, and hence not a good idea.
Services:
Here is a better solution for you, entirely within the AngularJS paradigm: AngularJS services
Excerpt from the link in point 3:
Data should also be stored in services, except where it is being bound
to the $scope. Services are singletons that persist throughout the
lifetime of the application, while controllers are transient between
application states. If data is stored in the controller then it will
need to be fetched from somewhere when it is reinstantiated. Even if
the data is stored in localStorage, it's an order of magnitude slower
to retrieve than from with a Javascript variable.
You can use the service to set and get your data inside your controller anywhere in the app in a consistent manner.
Here is an indicative example:
app.factory('formDetails', formDetails);
function formDetails() {
var formData = {};
return {
getProperty: function () {
return formData;
},
setProperty: function(values) {
formData = values;
}
};
};
Use it in your controller as:
app.controller('MyController', [ '$scope', 'formDetails' , function($scope, formDetails) {
$scope.checkboxData = {};
// on load call service 'get' function
$scope.checkboxData = formDetails.getProperty();
// on some event/watch function call service 'set' function
formDetails.setProperty($scope.checkboxData);
}]);

Self Populating AngularJS Factories

I'm looking for some input on exactly how to accomplish the following design pattern.
Background: I have two factories and a controller:
FirstFactory: This is the data storage that contains all the data the application relies on to function
SecondFactory: This is a list of $http.get methods. The getAllCities method just returns a promise
Controller: This is where the data resolves from SecondFactory and then is set into FirstFactory.journey.
Now currently the controller works fine but I am trying to have the data, from SecondFactory.getAllCities() resolve itself in the FirstFactory on runtime instead of waiting for the Controller to update it.
So currently I have a controller that does the following:
build = function() {
return SecondFactory.getAllCities()
.then(function(response) {
FirstFactory.journey = response;
});
};
This works fine and updates the factory with a the data returned from the method SecondFactory.getAllCities(). However I feel that the controller shouldn't be what sets up the default or init data set, I think the factory should accomplish this on it's own.
I assumed, probably incorrectly, that the following would work as instead of doing the call to the SecondFactory inside the controller, I was just moving this call to the FirstFactory so it can resolve itself when its instantiated instead of relying on the controller to populate the FirstFactory.journey with data.
var build;
//This is a call to a factory that contains the data
//I want to grab and store this in my factory on run
build = function() {
SecondFactory.getAllCities()
.then(function(response) {
//Why does this not get returned?
console.log(response);
return response
})
};
//This is the factory object that is returned
return {
journey: build()
}
However the above doesn't work. The console.log in the build function contains the data I require but it isn't being returned by that function. Is this an issue with my implementation of the promise or a broader design pattern issue?

Use return data from an angular service resource across all controllers with only one call

I have a custom Web API written in .NET that returns user's information that will be used in my AngularJS application. I want to be able to call my API once, and then use that returned JSON across my entire AngularJS application without having to recall the API within each of my controllers.
I currently have a factory of services, one of which returns all of the client's details I need to use the in rest of the services.
.factory('customApiService', function ($resource) {
return {
userInfo: function(userId, callback){
var api = $resource('../../api/UserInfo/:userId', {
userId: userId
}, {
fetch: 'JSONP',
'query': { isArray: false }
});
api.fetch(function (response) {
callback(response);
});
}
}
)
Now I don't want to call this userInfo service in every controller, but I do want the data to be passed into each without calling my API multiple times.
customApiService.userInfo(userId, function (d) {
var gaProfileId = d.gaProfileId;
var yelpId = d.yelpId;
var tripAdvisorId = d.tripAdvisorId;
var facebookPageName = d.facebookPage;
var twitterHandle = d.twitterHandle;
var clientName = d.clientName;
var searchlightAccountId = d.searchlightAccountId;
var searchlightDomain = d.searchlightDomainId;
}
You can try global variables .
use a $rootScope https://docs.angularjs.org/guide/scope
$rootScope is available in all controllers an templates .Just inject $rootscope in your controller or wherever required.
From what I read of your description and responses to other questions, it sounds like you're trying to make an asynchronous call before the rest of your app starts up. This is possible, but complex, and sort of voids the point of Angular in the first place. As I see it, you have two options:
QUICK HACK: If you really want this kind of behavior, why start your app at all? Do your request first, before you define your app in the first place, then define your app in the result handler for the request.
RIGHT WAY: Alter the behavior of your services and controllers to tolerate not having enough information to fully start. A lot of times this is less difficult than it sounds. Usually you can just chain a promise into their initialization block of code to wait for the data you need. Take a look at Brian Ford's "Angular Modal" project, at the lines of code I've highlighted here:
https://github.com/btford/angular-modal/blob/master/modal.js#L25-L36
This technique sets up a promise to return from the function. If the data it needs is already loaded from the service, it resolves the promise immediately. Otherwise, it makes the call to get what it's after, and you can see later (line 39) that the module uses promise.then() to wait until it has the data it needs to run.
This is a great pattern for both controllers and services when working with asynchronous data.
If using a $resource call instead, note that most $resource calls return a promise in a property called $promise. You can do something like this:
var MyController = function($scope) {
// This will get set soon!
$scope.myData = null;
var myResource = $resource('/path/to/:someId', { someId: '#id' });
myResource.get({ someId: 1 }).$promise.then(function(data) {
$scope.myData = data;
});
};
You can do more things in the .then() resolution callback for the promise, like initialize more parts of your controller, etc. There are also ways you can delay starting your entire controller until the resource is available. One really cool way is if you happen to be using the Angular ui-router module, there is a "resolve" option when defining each route. You can use that to call the $resource as shown above, and ui-router will wait to start your controller/view until it has what it needs.

push data from one controller to another, $resource service

I'm using angular routing for a SPA with a sidebar (on index.html) that loads a list of categories from a categoryListController, which has a categoryData $resource service injected for retrieving the category list.
Then i have a template, addCategory.html which adds a category with the help of a addCategoryController, which also uses categoryData $resource service.
$scope.categories = categoryData.query(); //categoryListController (for sidebar)
categoryData.save(newCategory) // on addCategoryController (for addCategory.html)
The problem is, the sidebar won't update unless I refresh the entire page. I'm thinking i've got to somehow tell the categoryListController to refresh, but i'm not sure how to do that. I can do $scope.categories.push(newCategory) right after categoryData.save(newCategory), and get the new category showing immediately on addCategory.html, but i don't think that's the answer for my sidebar, unless this is something that needs to be handled with $rootscope? I'm not sure. Thanks
One of the approach that you can take here to update the list of categories in categoryListController would be to use $rootScope to broadcast message detailing the category added.
Catch this message in the list controller to either fetch the list again from server or use the newly added item send using the broadcast message to the list.
Something like this in the Add controller
$rootScope.$broadcast('categoryAdded', { 'category': newcategoryObject });
Something like this in list controller
$scope.$on('categoryAdded', function (event, args) {
$scope.categories.push(args.category);
});
You can inject $rootScope as a dependency into the controller.
You can do a similar thing by creating a CategoryList service too. Since service are singleton by nature and can be shared across controllers, using the service approach you would define a CategoryList service with methods to get and `add' categories and bind to data returned by this service.
You should create a service that share the data structure and care of managing the content.
Something like this:
angular.service('categoryService', function() {
var categories = [], initilized;
return {
this.getCategories = function() {
if (!initialized) {
// call resource to fulfill the categories array
initialized = true;
}
// you cold return a promise that would be resolved as soon
// as you get the first response from server
return categories;
});
this.addCategory = function(category) {
// code to call $resource, add the category and update the
// categories array, shared between both controllers
//
// you could return the promise for adding the content
});
this.removeCategory = ...
};
});
 
You wouldn't need to even call $resource, this service would care of any need of persisting. Of course, you might change and add more method if you need to expose the promises.

Initializing/populating select boxes on page load in AngularJS

I'm writing a web application using AngularJS. I use a third-party library (that provides an Angular service) to fetch values from a database, and then use those to initialize some dropdown/select boxes on a page.
So, I have simple select boxes like this:
<div ng-controller="ChoiceCtrl">
<select ng-model="selectedFoo" ng-options="foo in foos"></select>
<select ng-model="selectedBar" ng-options="bar in bars"></select>
</div>
And a corresponding controller that initializes the choices for the select boxes. The service I'm using calls the given callback function after it receives values from the database. (The callback functions could be refactored into one but I'm using separate ones for clarity.)
angular.module('choice').controller('ChoiceCtrl', function($scope, ThirdPartyService) {
$scope.selectedFoo = '';
$scope.selectedBar = '';
$scope.foos = '';
$scope.bars = '';
var fooCallback = function(result) {
$scope.foos = result;
$scope.$apply;
}
var barCallback = function(result) {
$scope.bars = result;
$scope.$apply;
}
ThirdPartyService.asyncGetData('fetchFooOptions', fooCallback);
ThirdPartyService.asyncGetData('fetchBarOptions', barCallback);
});
The database calls are asynchronous and finish after the page has been rendered for the first time, so I manually call $scope.$apply in each callback function.
Is this the right way to initialize dropdown/select boxes in an AngularJS app when the values are fetched asynchronously when loading a page?
I've read tutorials saying that calling $scope.$apply manually is always a "code smell"... But since I'm fetching the values from a database, the operation happens "outside of Angular" which I believe makes those calls justified - and actually necessary.
I'm also wondering if the controller is the right place for these calls. In the tutorials I've read the options are always set in the controller but those sandbox examples never have an asynchronous database call happening.
You should modify three things in your code
The service should return a promise :Refer to documentation of angular for creating promise
Inside service resolve the promise when data is recieved from the server
Inside controller just assign proper values to bar and foos when promise is resolved
Remove $scope.apply since now you are modifying the values inside proper angular scope
Link:Use Promise and service together in Angular

Resources