I'm having a issue with angular services. The code included are 2 factory services. The values in the services are used to populate a slider in view.
I've tried for a day before asking. I've reviewed a couple posts here stackoverflow post and the post linked.
The first function references a $http GET to a json file. The second function are the values hard coded.
The slider program is able to display the required fields from gloveSize() with no issue.
But putting the exact same info in a json file the slider issues undefined.
function glvType($http) {
function getGloves() {
return $http.get('./assets/test.json').success(function (data) {
return data;
})
}
return { getGloves:getGloves }
}
function gloveSize() {
function getGloveSize() {
return [{ value: '10.50', legend: 'Youth Baseball' },
{ value: '11.00', legend: '2B/SS', id: 'bfbee3fb9893fc6d8555bbfa06176619' },
{ value: '11.25' },
{ value: '11.50', legend: 'Pitcher' },
{ value: '11.75', legend: '3B/Pitcher' },
{ value: '12.00' },
{ value: '12.25', legend: 'Softball Inf' },
{ value: '12.50', legend: 'Outfield' },
{ value: '12.75', legend: 'OF/1st Base' },
{ value: '13.00' }];
}
return { getGloveSize:getGloveSize }
}
In the glvType function console.log of the data is there. In the controller,following answer from other posts, understanding the concept of promise functionality.
Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 3 moreā¦ ]
$scope.product = gloveSize.getGloveSize();
$scope.glvSpec = glvType.getGloves().then(function (data) {
$scope.gloveSpec = data;
for (var i; i < $scope.gloveSpec; i++) {
console.log($scope.gloveSpec[i].value);
}
});
From here, I tell the slider directive to pull array data from $scope.glvSpec, however the results contiue are undefined.
A console.log in the then(function) shows that the info is there.
Object { data: Array[13], status: 200, headers: fd/<(), config: Object, statusText: "OK" }
Lastly, the scope.product variable you see in code is how I pull the static function array into the controller. Adding this to the directive options, displays the values as designed.
Thanks for any guidance.
Change your getGloves() to return the $http call itself instead of using the success method to return data - then data will be available in your .then params:
function getGloves() {
return $http.get('./assets/test.json');
}
Your loop needs to be fixed like so:
for (var i = 0; i < $scope.gloveSpec.length; i++) {
console.log($scope.gloveSpec[i].value);
}
I've also put a plunker together for you to show you how you achieve this with angular.
Make your $http call in a service (DataService) and inject that into your component controller. Then you can ask the DataService for your data and handle accordingly.
http://plnkr.co/edit/ZJW12W4kk0paBshgtfIG?p=preview
Related
This question already has answers here:
Wait until all jQuery Ajax requests are done?
(22 answers)
Closed 3 years ago.
Let me just start this by saying I've done a series of searches online, but can't seem to piece it together.
Requirements: Use jQuery :(
On click, I am using a .getJSON call to get an object with several layers.
Here's an example of the data:
myObj = {
title: 'some name',
items: [
{
name: 'item-1',
url: '/item-1'
},
{
name: 'item-2',
url: '/item-4'
},
{
name: 'item-3',
url: '/item-4'
},
{
name: 'item-4',
url: '/item-4'
},
]
}
I want to loop through all of the urls, and call an .ajax operation on them, and then store the new data I get back in their respective objects.
It would look like this:
myObj = {
title: 'some name',
items: [
{
name: 'item-1',
url: '/item-1',
properties: {//whole new set of data from url}
},
{
name: 'item-2',
url: '/item-4',
properties: {//whole new set of data from url}
},
{
name: 'item-3',
url: '/item-4',
properties: {//whole new set of data from url}
},
{
name: 'item-4',
url: '/item-4',
properties: {//whole new set of data from url}
},
]
}
Once all of that is complete and each object has this new bit of data, I then want to do something with the myObj, like render it to a jquery template (ugh), but the new data MUST be inside of each item.
Here's what I have so far:
var myItems = myObj.items;
$(myItems).each(function(index, item) {
var itemUrl = '/somestuff/' + item.url + '.js';
$.getJSON(itemUrl).done(function(itemData) {
item.data = itemData;
});
}).promise().done(function() {//render data to template})
The only problem I'm having is that sometimes the data doesn't exist yet (item.properties) when the template renders, and therefore cannot render undefined.
I've tried unsuccessfully chaining .done(), and have now come across using .when(), but don't know how to write the line of code to make .when() work properly.
Any help is appreciated, and I'd be happy to clarify details.
If you capture the Promise (technically a jQuery Deferred object, actually) generated by each AJAX request, and add them to an array, then you can call .when() to execute some code once all of the Promises are resolved. Something like this (untested):
var myItems = myObj.items;
var promises = [];
$(myItems).each(function(index, item) {
var itemUrl = '/somestuff/' + item.url + '.js';
var p = $.getJSON(itemUrl);
p.then(function(itemData) {
item.data = itemData;
return itemData;
});
promises.push(p);
});
$.when.apply($, promises).then(function() { //render data to template...
This is probably preferable to chaining the done() callbacks, because it still allows the requests to execute in parallel, which is likely to be faster (although this is somewhat dependent on the server, but that's a separate issue).
I have autoGroupColumnDef and I want to setup text filter. But values of the column come from getDataPath method. But I need another value in the filter.
autoGroupColumnDef: {
headerName: "Systems",
filter: 'text',
valueGetter: function(params) {
var result = params.data.hospName || params.data.hospitalSystem;
return result;
},
cellRendererParams: {
suppressCount: true,
innerRenderer: function(params) {
var result = params.data.hospName || params.data.hospitalSystem;
return result;
}
}
},
After trying on couple of things,
Option 1: You can make use of [filterParams][1]. This only helps to play around with options/choices in the filterMenu..
function filterCellRenderer(params) {
//other than params.value nothing else will be there..
// params.data won't be there when its called from filter popup
return params.value+" Custom";
}
var gridOptions= {
...,
treeData: true,
components: {
...,
filterCellRenderer: filterCellRenderer
},
autoGroupColumnDef: {
...,
filterParams: {
cellRenderer: 'filterCellRenderer',
//values: ["A", "XYZ"] //you can feed directly specific values. These need to be part of filePath. Else filtering won't work.
}
}
}
Option 2: If you are looking for custom filter (tweak with GUI), or you want to post processing after it has been configured by ag-grid you can define the following:
var gridOptions = {
...
getMainMenuItems: getMainMenuItems,// function to build your own menu
postProcessPopup: function(params){
// edit the popup..
//params.type gives whether its column menu or not.
//params.ePopup gives handler to popup which you can modifiy.
},
...
}
OR you can build your own custom filter as described here
Let me start off by saying I am fairly new to this.
So what I'm currently doing is I'm playing around with the live feed chart using a js function that produces and stringifies random numbers.
window.feed = function(callback) {
var tick = {};
tick.plot0 = parseInt(10+900*Math.random(), 10);
callback(JSON.stringify(tick));
};
The first issue I'm trying to tackle is being able to switch charts with the click of a button without the feed restarting, essentially having the feed function running in the back and (I'd assume) storing the data into an array? Would that be the correct approach? But currently, when I click the button it just restarts the feed. Here's the code:
$('#chartButton').bind('click', function(){
zingchart.exec('chart', 'setdata',{
'data': {
'type': 'bar',
"refresh":{
"type":"feed",
"transport":"js",
"url":"feed()",
"interval":200
},
'series':[
{
'values':[]
//[11,26,7,44,11]
},
{
'values':[]
//[42,13,21,15,33]
}
]
}
});
});
$('#lineButton').bind('click', function(){
zingchart.exec('chart', 'setdata',{
'data': {
'type': 'line',
"refresh":{
"type":"feed",
"transport":"js",
"url":"feed()",
"interval":200
},
'series':[
{
'values':[]
// [11,26,7,44,11]
},
{
'values':[]
// [42,13,21,15,33]
}
]
}
});
});
$('#areaButton').bind('click', function(){
zingchart.exec('chart', 'setdata',{
'data': {
'type': 'area',
"refresh":{
"type":"feed",
"transport":"js",
"url":"feed()",
"interval":200
},
'series':[
{
'values':[]
// [11,26,7,44,11]
},
{
'values':[]
// [42,13,21,15,33]
}
]
}
});
});
And lastly, I'm trying to make it so it has two different "values" being displayed on the chart, but I can't seem to figure out how I would do that. The tutorial says if you're going to use two values inputs create the objects, but doesn't extrapolate on how to get the different values transmuted.
My hunch is that I create the feed function, but store all the values being created into an array, one for each function. Then assign those arrays to be the values of the chart, but I've been having trouble figuring out exactly how to increment through an array in javascript so you can keep adding more and more data to it as it is created. Any help would be much appreciated.
I started playing with highcharts for a project I am doing. Highcharts was displaying properly when I dumped a massive array of data into it, but now that I am trying to parse through groups of data that I retrieved through MongoDB I can't get it to display.
Here is my angular
$scope.retrieveData = function(){
$http.get('/calldata').then(function(response){
$scope.toneDatas = response.data
var idArray = []
angular.forEach($scope.toneDatas, function(value, key) {
idArray.push({id: value._id, social_tone_data: value.social_tone_data})
for (var i = 0; i < idArray.length; i++) {
if (idArray[i].id === value._id) {
console.log(idArray[i].id)
var socialToneName = []
var socialToneScore = []
angular.forEach(value.social_tone_data, function(value, key) {
socialToneScore.push(value.tone_score)
socialToneName.push(value.tone_type)
})
$("#" + value._id).highcharts({
chart: {
type: 'bar'
},
title: {
text: 'Fruit Consumption'
},
xAxis: {
categories: socialToneName
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: [{
data: socialToneScore
}]
});
};
};
})
});
};
When the page loads a get request calls the database and gets the data to be served to the web page, and I am trying for now to get the data group social_tone_data to display on a chart. I have 19 documents in my mongo database and want it so that each time the loop completes, one chart is generated and served to my webpage. I should have 19 charts. I am still playing around with the code but any help is appreciated.
UPDATE
I refactored my code through an angular directive and used the element argument to display on the page.
Some good info using NG-Highcharts.
as others have said, use a directive to modify dom elements, not controller & def not jQuery as updates fall outside of angulars digest loop.
Your example needs the supplemental template/html code to be relevant.
I want to retrieve all available State values for Rally Defect.
The following code works good for Features:
this.states = [];
this.stateStore = Ext.create('Ext.data.Store', {
fields: ['_ref', 'name']
});
Ext.create('Rally.data.wsapi.Store', {
model: 'State',
autoLoad: true,
filters: [
{
property: 'Enabled',
operation: '=',
value: true
},
{
property: 'TypeDef.Name',
operation: '=',
value: 'Feature'
}
],
listeners: {
load: function (store, data) {
for (var i = 0; i < data.length; i++) {
this.stateStore.add({ '_ref': data[i].data._ref, 'name': data[i].data.Name });
}
this.statesLoaded = true;
this._initialLoad();
},
scope: this
}
});
With this approach, we load all available State values for features. However, when I change 'Feature' TypeDef.Name filter to 'Defect', I get nothing despite the fact that there are many active States for Defect defined.
Does anybody know why this happens and how get State values for Defect?
Maybe Defects use some other states, not like features, suer stories etc?
In WS API there is a full State object that represents State of PortfolioItems. It is different from the State or ScheduleState of such artifacts as Defect or UserStory, which are only string values in the dropdown field. There is no such thing as State.Name for a Defect.
Using promises, this may look like this:
launch: function(){
this._getModel().then({
success: this._getAllowedValues,
scope:this
}).then({//...})
},
_getModel:function(){
return Rally.data.ModelFactory.getModel({
type:'Defect'
});
},
_getAllowedValues:function(model){
var deferred = Ext.create('Deft.Deferred');
var allowedStateValues = [];
model.getField('State').getAllowedValueStore().load({
callback: function(records,operation,success){
Ext.Array.each(records,function(allowedValue){
allowedStateValues.push(allowedValue.get('StringValue'));
});
if(success){
deferred.resolve(allowedStateValues);
}
else{
deferred.reject();
}
}
}) ;
return deferred.promise;
},//...
See this example that retrieves allowed values for Priority and Severity of defects. Since those allow null values, null values are removed in this app example, but State does not have null values so you may skip that step.