I am new to Angular, and am having an issue where my $http url placeholders are not being replaced by the actual data. What I want is for this:
"/json/:searchType/:userId"
To be replaced with this when I use my $http call:
"/json/user/123"
Instead, I get something like this, according to firebug's Net tab:
"/json/:searchType/:userId?userId=123&searchType=user"
I have tried to create a fiddle, but because I use different views and json data from a server, I'm not sure how to create something that works in the fiddle that still looks anything like what I am actually doing. I have looked at this answer, this answer, this answer, this answer, and this answer, to name a few. I'm having trouble finding a posting that isn't about $resource, or the # notation it uses to link url params to object params though.
To explain, I'm using a service to pass the searchType and accountId params between controllers and my factory, which actually performs the $http request.
Here is my controller:
.controller('UserDetailsCtrl', ["$scope", "Search", function ($scope, Search) {
$scope.result = Search.getUser();
}])
Here is my Factory:
.factory('Search', ["$http", "SearchCriteriaSvc", function($http, SearchCriteriaSvc) {
var baseUrl = "/json/:searchType/:accountId";
return {
getUser: function () {
return $http.get(baseUrl,
{params:
{
accountId: SearchCriteriaSvc.getAccountId(),
searchType: SearchCriteriaSvc.getSearchType()
}
})
.then(function(result) {
return result.data;
});
}
}
}])
Finally, my service:
.service('SearchCriteriaSvc', function() {
var searchType = "",
userId = "";
return {
getSearchType: function () {
return searchType;
},
setSearchType: function(value) {
searchType = value;
},
getUserId: function () {
return userId;
},
setUserId: function(value) {
userId= value;
}
};
})
I have tried not using the service to pass the params (just manually typing in strings) and I get the same result, so I don't think that my service is the issue, but then, I'm at a loss.
Any help would be great. Thanks!
$http doesn't work in that way. You will have to collate your parameters into a URL yourself.
You are probably thinking of $resource which allows you to predefine HTTP request URLs and their parametric components, or $route which also allows similar parametric URL functionality but within the context of your angular front end rather than back end.
Any params passed in the way you pass them will end up as query / GET style parameters.
http://docs.angularjs.org/api/ng.$http
params – {Object.<string|Object>} – Map of strings or objects which will be turned to ?key1=value1&key2=value2 after the url. If the value is not a string, it will be JSONified.
Related
I have an angular project. I am making an html/angular form - getting the data from a stored procedure via $http get in a service in angular. Now I want to databind some of the drop down lists in my filter that's in this html form. I have the data in a view which I made models for and added to the entity framework. How should I make calls to this breeze in angular? Code example please? in service or in controller?
------here's what i've tried--------------
what am I doing wrong here? (may be a few things...i'm new to angular. Then I just want to be able to somehow call this function populatestyleddl in my ng-model or something....
.factory('sellingService', ['$filter', '$http', function ($filter, $http) {
function PopulateStyleDDL() {
return breeze.EntityQuery.fromEntityNavigation('v_Style')
.using(context.manager).execute();
};
//check if above function is legal
function SalesStatus(filter) {
console.log(breeze);
return $http({
method: 'GET',
url: '/Services/SalesStatus',
params: { filter.itemStyle }
}).then(function (result)
{ return result.data; })
}
return {
SalesStatus: SalesStatus
};
}]);
--------------------------------here's what i have now.....
ok, here is what i've got now. this is happening in a js file where all my breeze calls are. Can you confirm if my syntax here is right and how my function syntaxically should look in my factory (and also how my syntax should look in my controller...)
function GetStyles() { return breeze.EntityQuery .from("v_Style") .using(manager) .execute(); }
#LisaSolomon, regarding your syntax:
function GetStyles() {
return breeze.EntityQuery
.from("v_Style")
.using(manager)
.execute();
}
Looks good with the information I have. If it's not working I'd make sure:
The controller has a properly-defined v_Style action, and
The manager is defined and has the correct service name
So, assuming that is correct, you will need to add it to your returned object so that it is available in your controller:
return {
SalesStatus: SalesStatus,
GetStyles: GetStyles
};
Then to use it in your controller, you will need to reference the .then() of the promise
$scope.styles = '';
sellingService.GetStyles().then(function(data) {
$scope.styles = data.results;
}).catch(function(err) {
// error processing
});
Any error messages you're getting would be helpful. If there's any chance you could show controller and view code so we could build a fiddle, that would be great, too.
I have a partial from which I need to call a route which will have a controller and a view of its own. When I call the route, I also need to pass a json object to the controller. I have done this earlier for simple values like id, name etc but in that case, I passed it as path param and I can retrieve it using the $routeparams. But how to do the same with json object. Please let me know.
You could use a factory to save data from one controller and retrieve it from an other controller.
Something like this?
angular.module('app')
.factory('mySerivce', function() {
var jsonData;
return {
setData: function(data) {
jsonData = data;
},
getData: function() {
return jsonData;
}
}
});
setData from the first controller and from the second getData.
Recently it has become possible to use angularjs within google apps script via the iframe sandbox mode.
My problem comes when trying to communicate with the server (gapps spreadsheet) and receiving asynchronous data in return.
The implementation for receiving data from the server is to use a function with a callback function like so:
google.script.run.withSuccessHandler(dataGatheringFunction).getServerData();
getServerData() would be a function that resides server-side that would return some data, usually from the accompanying spreadsheet. My question is how to use the callback function within the parameters of AngularJS. A typical $http function could be placed in a provider, and the scope value could be populated after then.() returns. I could also invoke $q. But how would I deal with the necessity of google's callback?
Here's a simplified version of what I'm messing with so far:
app.factory("myFactory", function($q){
function ssData(){
var TssData = function(z){
return z;
}
google.script.run.withSuccessHandler(TssData).getServerData();
var deferred = $q.defer();
var d = deferred.resolve(TssData)
console.log("DP: " + deferred.promise);
return deferred.promise;
}
return ssData();
})
Then in the controller resolve the server call similar to this:
myFactory.then(set some variables here with the return data)
My question is simply - How do I deal with that callback function in the provider?
The script throws no errors, but does not return the data from the server. I could use the old $timeout trick to retrieve the data, but there should be a better way.
You only need to $apply the output from the server function:
google.script.run.withSuccessHandler(function(data) {
$scope.$apply(function () {
$scope.data = data;
});
}).withFailureHandler(errorHandler).serverFunction();
Maybe the most elegant solution that makes sure the google.script.run callbacks are registered automatically in the AngularJS digest cycle would be to use the $q constructor to promisify the google callbacks. So, using your example above:
app.factory('myFactory', ['$q', function ($q){
return {ssData: ssData};
function ssData(){
var TssData = function(z){
return z;
};
var NoData = function(error) {
// Error Handling Here
};
return $q(function(resolve, reject) {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)
.getServerData();
}).then(TssData).catch(NoData);
}
}]);
Then in your controller you can call myFactory.ssData()
Since I don't know exactly what TssData is doing I included it here but note that this simply returns another promise in this context which you will still have to handle in your controller:
myFactory.ssData().then(function(response) {
// Set data to the scope or whatever you want
});
Alternately, you could expose TssData by adding it to the factory's functions if it is doing some kind of data transformation. If it is truly just returning the response, you could refactor the code and omit TssData and NoData and handle the promise entirely in the controller:
app.factory('myFactory', ['$q', function ($q){
return {ssData: ssData};
function ssData(){
return $q(function(resolve, reject) {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)
.getServerData();
});
}
}]);
app.controller('myController', ['myFactory', function(myFactory) {
var vm = this;
myFactory.ssData()
.then(function(response) {
vm.myData = response;
}).catch(function(error) {
// Handle Any Errors
});
}]);
An excellent article about promises (in Angular and otherwise) is here: http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
This guy seems to be pulling data from a GSheet into angular quite happily without having to do anything fancy.
function gotData(res) {
$scope.validUser = res.validUser;
var data = angular.copy(res.data), obj, i=0;
Object.keys(data).forEach(function(sh) {
obj = {title: sh, checked: {}, showFilters: false, search: {}, sort: {index: 0, reverse: false}, currentPage: 0, checkedAll: true, showBtns: true, searchAll: ''};
obj.heading = data[sh].shift();
obj.list = data[sh];
obj.heading.forEach(function(s,i) {
obj.checked[i] = true;
});
$scope.sheets.push(obj);
});
$scope.sheets.sort(function(a,b) {
return a.title > b.title ? 1 : -1;
});
$scope.gotData = true;
$scope.$apply();
}
google.script.run.withSuccessHandler(gotData).withFailureHandler($scope.gotError).getData();
My solution was to get rid of the $q, promise scenario all together. I used $rootScope.$broadcast to update scope variables from the server.
Link to spreadsheet with script.
I'm looking for a simple example to follow where I use the response of a request to initiate additional GET requests.
I have 2 services - one returns a list of search results objects including an ID - a second which takes this ID and returns an image.
For example:
myApp.factory('Search', ['$resource', function($resource){
return $resource('/api/search/', {}, {
getResults: {method:'POST'}
});
}]);
myApp.factory('Image', ['$resource', function($resource){
return $resource('/api/image/', { id: '#id' }, {
get: {method:'GET'}
});
}]);
How can update my controller to use the output JSON of the first call to retrieve the images?
myApp.controller('myAppController', function($scope, Search, Image) {
$scope.searchResults = Search.getResults();
});
Thanks.
You can chain promises (which is what resources is working on) by either nesting your calls or have the previous success method return a promise and then hatch onto that.
Depending on your scenario, this could be a simple solution:
Search.getResults(function (results) {
var imageId = results[0].imageId; // don't know what you need
$scope.images = Image.get({id: imageId});
});
I asked the wrong question yesterday (and got a goodanswer that worked), but am realizing it's not what I needed. I need to be able to retrieve JSON data (preferably once), store it, and access it throughout my service. The challenge I'm having is that all the examples I can find talk about using JSON and passing to the app/controller, whereas in this case I need to get it, check it, and then it dictates what my module/service does.
For instance, I have my App and Controller, and then I have a module such as (this is psuedo-code, not meant to run):
angular.module("myModule")
.service("myService1", function($q, myService2, $http) {
this.getModel = function() {
return {
title: "My Title",
desc: "My Desc"
options: function () {
if (condition A)
return "option1";
else
return "option2";
}
};
};
})
.service("myService2", function($q, $http) {
this.getCfgInfo = function () {
var defer = $q.defer();
$http.get("my/json/url").then(function(response) {
defer.resolve(response.data);
});
return defer.promise;
};
})
In this example, I'm wanting to get the JSON, and use it within myService1 for both literal values (title, desc) as well as for conditions (condition A within the if).
I know I can do something like this (thanks to Joel for helping yesterday):
service("myService1", function($q, myService2, $http) {
// get a promise object for the configuration info
var cfgProm = rtDataMapper.getCfgInfo()
this.getModel = function() {
return {
title: cfgProm.then(function(response) {
return response.JSON_NAME;
}),
and it works fine as I've got the title mapped back into my model and there is a watch(), but I'm stumped as to how I get, store, and use the JSON within the service itself as a conditional (i.e. if (condition A) where condition A is coming from the JSON. Trying to wrap these in .then() doesn't seem to make sense, or at least I can't figure out how to do it.
I'm new to Angular and am attempting to modify some code that was left to us. I'm guessing I don't need the myService2 just to get the JSON. Can anyone help point me in the right direction? I've spent several hours online but can't seem to find a relevant reference/example.
Thanks
Live demo (click).
I'm having the service immediately get the data when it is injected (that code will only run once no matter how many times you inject it). That's nice because you won't have to call a function to get the data - it's called for when creating the service.
Your service method that returns that data will need to return the promise of the data, of course, since you aren't guaranteed that it will have come through when you ask for it. You can pass arguments to that method to use to determine your conditions. All you need to do for that is use promise.then in the method and resolve the promise with the modified data. Since that method is returning the promise already, the modification will be updated on the resolve. See all of this below and in the demo.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, myService) {
myService.getData(15).then(function(data) {
$scope.myData = data;
});
});
app.factory('myService', function($q, $timeout) {
//this code only runs once when you first inject the service
//get data immediately
var deferred = $q.defer();
$timeout(function() { //simulate ajax call
var data = { //ajax response data
foo: 15,
bar: 'Some data!'
};
data = modifyData(data, 1);
deferred.resolve(data);
}, 500);
function modifyData(data, fooVal) {
if (data.foo === fooVal) {
data.baz = 'Conditional data!';
}
return data;
}
var myService = {
//data can be modified when it comes from the server,
//or any time you call this function
getData: function(fooVal) {
if (fooVal) { //if you want to modify the data
deferred.promise.then(function(data) {
data = modifyData(data, fooVal);
deferred.resolve(data);
});
}
return deferred.promise;
}
};
return myService;
});