How to assign array of object to dropdown in angularjs? - javascript

Hi I am developing web application in angularjs. I have one html form with several drop downs. I am making api calls to fill data to drop down. Instead of making separate call in one call i am getting all data required to bind all drop downs.
Below is my sample data.
{"status":"Success","msg":"Success","code":"200","data":{"Education":[{"ID":1,"Education":"btech"},{"ID":2,"Education":"Bcom"},{"ID":3,"Education":"BA"},{"ID":6,"Education":"PU"}],"MaritalStatus":[{"ID":1,"MaritalStatus":"sinle"},{"ID":2,"MaritalStatus":"married"}]}
I am trying to bind it to drop down as below.
var martialstatus = new Array();
var Education = new Array();
$http.get(baseurl + 'api' + '/Customer/' + 'PersonalInfoMasters').success(function (data) {
$.map(data.data, function (item) {
Education.push(item[0]);
});
console.log(Education);
}).error(function (status) {
});
Abobe piece of code gets me first item from the each object like first item from education,martial status etc. I would like to bind education object to education array. May i know where i am missing any line of code? Any help would be appreciated.

You don't seem to do any kind of mapping from the original result, so the following would suffice:
Education = data.data.Education;
Note:
The item[0] looks strange - are you trying to achieve something with that ?
I would use lowercase for the name of the variable.

Try something like this:
var MaritalStatus = new Array();
var Education = new Array();
$http.get(baseurl + 'api' + '/Customer/' + 'PersonalInfoMasters').success(function (data) {
$.map(data.data.Education, function (item) {
Education.push(item);
});
$.map(data.data.MaritalStatus, function (item) {
MaritalStatus.push(item);
});
}).error(function (error) {
// handle API errors
});
If you do not even need to format the output, you can simply re-assign the original value of your variable.
$http.get(baseurl + 'api' + '/Customer/' + 'PersonalInfoMasters').success(function (data) {
Education = data.data.Education;
MaritalStatus = data.data.MaritalStatus;
}).error(function (error) {
// handle API errors
});

You can do it this way:
var martialstatus = new Array();
var Education = [];
$http.get(baseurl + 'api' + '/Customer/' + 'PersonalInfoMasters').success(function(data) {
$.map(data.data.Education, function(item) {
Education.push(item);
});
}).error(function(status) {
});
You just need to push item instead of item[0] in the .map() method so it takes the whole Education object and push it in your array.
Otherwise you can just use with no need to use the $.map():
Education = data.data.Education

Shouldn't it be more like:
$.map(data.data.Education, function (item) {
Education.push(item[0]);
});
?

Related

Knockout Check If Existing in observableArray before Push

I am new to Knockout and I have a little problem stopping me from completing my simple project.I have an observableArray called loanDeductions that I display in a table with foreach binding. I have another observableArray called loanDeductionsList which is also from the json data of my first observableArray, I used it in my drop down list which when a value is selected, it will push the selected data to my table. If it didn't make sense as I cannot really explain it clearly, this is my javascript file:
var deductionLine = function (deductionID, deductionName, amount) {
self = this;
self.deductionID = ko.observable(deductionID);
self.deductionName = ko.observable(deductionName);
self.amount = ko.observable(formatCurrency(amount));
};
function LoanDeductions(deductions) {
var self = this;
self.loanDeductions = ko.observableArray(ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
}));
self.loanDeductionsList = ko.observableArray(ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
}));
self.selectedDeduction = ko.observable();
self.selectedDeduction.subscribe(function (data) {
self.loanDeductions.push({
deductionID: data.deductionID,
deductionName: data.deductionName,
amount: data.amount,
});
});
}
Can you help me find a way to make my function selectedDeduction.subscribe() push the data ONLY when the item to be pushed is not existing in my loanDeductions observableArray.
Any help will be greatly appreciated. Thank you!
I am somewhat aware that the way I populate my dropdown list may o may not be the best way to do it, I am open to suggestion of a better way and rewrite my program.
just to share what I did I added this line in my selectedDeduction.subscribe():
self.selectedDeduction.subscribe(function (data) {
var match = ko.utils.arrayFirst(self.loanDeductions(), function(deduction) {
return deduction.deductionID() === data.deductionID();
});
if (match) {
alert(data.deductionName() + ' already exists!');
} else {
self.loanDeductions.push({
deductionID: data.deductionID,
deductionName: data.deductionName,
amount: data.amount,
});
}
});

Can't create Meteor.js helper based on parse.com query

My meteor app accesses Parse.com to pull in and display data.
I started out integrating the parse.com javascript query directly into the template's rendered function, which worked well.
Now, I want to use the Parse.com query in a helper to pass it over to a meteor {{#each}} loop which lives in my template.
Template.dashboard.helpers({
app: function () {
//init new array
var appsArr = [];
//Create a Parse Query for Post objects
var query = new Parse.Query("Apps");
query.descending("createdAt");
var appsObj = {};
query.find({
success: function(results) {
// Add the returned Parse.Object values to appsArr
for (var i = 0; i < results.length; i++) {
appsObj = {};
appsObj.obid = results[i].id;
appsObj.title = results[i].attributes.title;
appsObj.screenshot1 = results[i].attributes.screenshot1._url;
appsObj.appIcon = results[i].attributes.appIcon._url;
appsArr.push(appsObj);
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
return appsArr
}
});
Every time I try and return my array (appsArr) in the helper I get the error :
"Exception in template helper: undefined". I also can't get my parse objects to output in the console. Again, the same code works in the rendered function.
I am fairly new to Meteor.js and Blaze templates. please help me implement this parse query into the helper correctly so I can {{#each}} in the template.
{{#each app}}
<h3 class="app-title">{{title}}</h3>
{{/each}}
Thanks in advance!
Because the query.find function is asynchronous and non-blocking, you can't just assign variables in the callback and return them outside of the callback -- the callback hasn't run by the time you hit the return statement, so you're returning something that hasn't been defined.
An easy way around this will be to use a reactive variable (a variable whose assignment is watched); you can either use [ReactiveVar][1] or the built-in reactive [Session][2] variable. I typically use Session. A possible implementation would be something like this (apologies for not testing this out ahead of time):
Template.dashboard.onRendered({ // onRendered, calculate appVar
Session.set('appsVar', null); // reset appsVar immediately -- can also do this in onCreated / onDestroyed to clean up
//init new array
var appsArr = [];
//Create a Parse Query for Post objects
var query = new Parse.Query("Apps");
query.descending("createdAt");
var appsObj = {};
query.find({
success: function(results) {
// Add the returned Parse.Object values to appsArr
for (var i = 0; i < results.length; i++) {
appsObj = {};
appsObj.obid = results[i].id;
appsObj.title = results[i].attributes.title;
appsObj.screenshot1 = results[i].attributes.screenshot1._url;
appsObj.appIcon = results[i].attributes.appIcon._url;
appsArr.push(appsObj);
}
Session.set('appsVar', appsVar);
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
});
Template.dashboard.helpers({
app: function() { return Session.get('appsVar'); } // This will re-run when Session.appsVar is updated in the callback above.
});

Building OData $filter URLs with an Angular provider

I have an angular provider for querying an OData service.
Now I'm trying to build a $filter function onto that provider, so I can use it throughout my app.
The problem I'm running into, and so far haven't been able to solve, is that the query part of the URL needs to start with '$filter=' which I can handle fine when there is one filter, but multiple filters are added as ' and {query goes here}'.
A sample query would be:
http://www.example.com/odata/Restaurants/?$filter=id eq 2 and city eq 'Los Angeles' and substringof("Lagasse", chef)&$top=20
I'm sending all the filters in an array to the provider. Ideally, I would use "$filter=#{firstFilter}" for the first filter in the array and for the remaining filters use " and #{remainingFilter}" but I'm unsure how to structure this code.
My current code uses multiple if statements to check if a filter is there, but with the nature of building the url, it makes one of the filters mandatory at all times. I'd like to avoid this.
For example:
var filter = "$filter=id eq 2";
if (city) {
filter += " and city eq #{cityName}";
}
if (chef) {
filter += " and substringof(#{chefName}, chef)";
}
Now everytime a user inputs a query, they have to specify an id.
We are NOT using BreezeJS, JayData, or any other library. Strictly AngularJS and specifically $http, NOT $resource.
You can use odata-filter-builder to build $filter part for OData URL query options.
Then just use $http with config params.
Short example:
var filter = ODataFilterBuilder()
.eq('id', 2)
.eq('city', 'Los Angeles')
.and('substringof("Lagasse", chef)')
.toString();
$http
.get(resourceUrl, {params: {$filter: filter, $top: 20}})
.then(function(response) {
// Handle response
})
Full example:
angular
.module('OData', [])
.constant('ODataFilterBuilder', ODataFilterBuilder)
.factory('ODataService', function($http) {
return {
load: function(resourceUrl, queryParams) {
return $http.get(resourceUrl, {params: queryParams})
.then(function(response) {
return response.data.value;
});
}
}
});
angular
.module('app', ['OData'])
.controller('appController', function($http, ODataService, ODataFilterBuilder, $httpParamSerializer) {
// 1. inject ODataFilterBuilder
// use short name for filter builder
var f = ODataFilterBuilder;
// 2. build filter
var filter = f()
.eq('id', 2)
.eq('city', 'Los Angeles')
.and('substringof("Lagasse", chef)')
// 3. creater odata query params
var queryParams = {
$filter: filter.toString(),
$top: 20
// TODO: add other params
};
// 4. prepare odata resourse URL
var odataServiceUrl = 'http://path/to/odata/service/';
var odataResourseUrl = odataServiceUrl + 'entity';
// 5. Do http request with odataResourseUrl and queryParams
// use ODataService or angular $http service
// ODataService
// .load(odataResourseUrl, queryParams)
// .then(function(value) {
// // handle value
// });
// OR
// $http.get(odataResourseUrl, {params: queryParams})
// .then(function(respons) {
// // handle respons.data.value
// });
// Result examles:
// NOTE: $httpParamSerializer - default $http params serializer that converts objects to strings
var queryParamsSerialised = $httpParamSerializer(queryParams);
// put values to 'this' to use it in html
this.queryParams = queryParams;
this.queryParamsSerialised = queryParamsSerialised;
this.queryUrl = odataResourseUrl + '?' + queryParamsSerialised;
});
<div ng-app="app" ng-controller="appController as vm">
<pre>queryParams: {{vm.queryParams|json}}</pre>
<pre>queryParamsSerialised: {{vm.queryParamsSerialised}}</pre>
<pre>queryUrl: {{vm.queryUrl}}</pre>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="https://npmcdn.com/odata-filter-builder#^0.1/dist/odata-filter-builder.js"></script>
I know you said you are not using any other library, but in case anyone else stumbles up this...I suggest using joData. It's very expressive and requires no other dependencies: https://github.com/mccow002/joData
Here is your example in joData:
var query = new jo('http://www.example.com/odata/Restaurants');
query.filter(new jo.FilterClause('id').eq(2))
.andFilter(new jo.FilterClause('city').eq('Los Angeles'))
.andFilter(new jo.FilterClause('chef').substringof('Lagasse').eq(true))
.top(2);
Then,
query.toString()
produces...
"http://www.example.com/odata/Restaurants?$top=2&$filter=id eq 2 and city eq 'Los Angeles' and substringof('Lagasse',chef) eq true"
Anyway, to set this up for Angular here is what I did...
Reference joData js in your html before your angular.js reference.
Wrap it in an Angular service
angular.module('app.shared.oData', [])
.service('oDataBuilderService', function () {
this.jo = jo;
};
Now other services can use this odata service to construct odata queries:
angular.module('app.shared.video', [])
.service('videoService', function ($http, oDataBuilderService) {
this.getByVideoCatalogId = function (videoCatalogId) {
var query = new oDataBuilderService.jo('http://www.example.com/VideoCatalog/OData');
var videoCatalogIdEquals = new oDataBuilderService.jo.FilterClause("VideoCatalogId").eq(videoCatalogId);
query.andFilter(videoCatalogIdEquals);
var queryAsString = query.toString();
var promise = $http.get(queryAsString);
return promise;
}
});
You can add $filter= at the end, but then you'd have the same problem with the "and "
Easier would be to just create a simple function
addFilter(currentFilter, filter) {
if (currentFilter.length == 0) {
currentFilter = "$filter=" + filter;
} else {
currentFilter += "and " + filter;
}
return currentFilter;
}
so then just call currentFilter = addFilter(currentFilter, "what to filter")
var currentFilter = "";
if (city) {
currentFilter = addFilter(currentFilter, "city eq #{cityName}");
}
if (chef) {
currentFilter = addFilter(currentFilter, "substringof(#{chefName}, chef)");
}
I've done similar and have what I think is an elegant solution with no dependencies on other libraries. I use Array.join and concatenate the filters with an "and" between them:
var filter = [];
if (city) filter.push("City eq '" + city + "'");
if (chef) filter.push("Chef eq '" + chef + "'");
var filterQuery = filter.join(" and ");
This assumes you always want "and" between them, (not or), but that is the case in my apps and in your example. I also do this to build up the url:
var parts = [baseurl];
parts.push("$top=10");
parts.push("$skip=" + skip);
parts.push(filterQuery);
var url = parts.join("&");

Format returned table data in json

I'm fairly new to javascript. I retreive data from a sql server database that looks like this :
[Object { shortcode="0013A2004031AC9A", latest_measurement=1067, keyid="6801"},
Object { shortcode="0013A2004031AC9A", latest_measurement=7, keyid="6802"},
Object { shortcode="0013A2004031AC9A", latest_measurement=8598838, keyid="6803"}]
I want to format this in a json like this :
{mac : 0013A2004031AC9A, keys : {6801:1067, 6802:7, 6803:8598838}}
but I just don't get to that.
I have
var jsonDataPerMac = {};
I loop over the json object above and for every new mac I find I do :
jsonDataPerMac[i]={"mac": device.shortcode, "keys":[]};
but how do I get to fill the keys?
Any hints would be appreciated.enter code here
var macs = [];
var jsonDataPerMac = {};
var i = 0;
$.ajax({
url: "/bmmeasurements",
type: "GET",
data: {"unitid" : unitid},
async: false,
success: function (data) {
console.log(data);
initializeTable();
$.each(data, function (index,device) {
//add all distinct macs in an array, to use them as a column header
if($.inArray(device.shortcode, macs) == -1) {
macs.push(device.shortcode);
jsonDataPerMac[i]={"mac": device.shortcode, "keys":[]};
i++;
//create a table cell for each possible key. id = 'mac-key'
createTableGrid(device.shortcode);
}
//add the measurement data to the correct cell in the grid
$('#' + device.shortcode + '-' + device.keyid).html(device.latest_measurement);
});
}});
Here is my proposition. I would rather avoid using jQuery to perform such a simple operations. In this particular example, we use forEach and for..in loop.
//new output array
var newArray = [];
//we traverse the array received from AJAX call
array.forEach(function(el) {
var added = false; // it's false by default
// we check if the mac is already in newArray, if yes - just add the key
for(var i in newArray) {
if(newArray[i].mac == el.shortcode) {
newArray[i].keys.push(el.keyid+":"+el.latest_measurement);
added = true; // tells us whether the key has been added or not
}
}
// if key hasn't been added - create a new entry
if(!added) {
newArray.push({"mac": el.shortcode, "keys":[el.keyid+":"+el.latest_measurement]});
}
});
console.log(newArray);
You can transform above code to a function and then, reuse it in your ajax onSuccess method. Remember to pass the array as an argument and to return newArray.
JSFiddle:
http://jsfiddle.net/2d5Vq/2/
You need to combine the entries first...
var reducedData = {};
$.each(macs, function(index,macitem){
if (reducedData.hasOwnProperty(macitem.shortcode)) {
reducedData[macitem.shortcode].push(macitem.key);
} else {
reducedData[macitem.shortcode] = [ macitem.key ];
}
});
And then map to your desired format inside an array...
var jsonDataPerMac = [],
i = 0;
$.map(reducedData, function(keys,mac){
jsonDataPerMac[i++] = {"mac": mac, "keys": keys};
// your other code goes here
});
Also your usage of jsonDataPerMac suggests that you want it to be an array.

Handling no results in jquery autocomplete

Hey I'm trying to return a message when there are no results for the users current query! i know i need to tap into the keyup event, but it looks like the plugin is using it
This question is really out of date, anyways I'm working with the new jQuery UI 1.8.16, autocomplete is now pretty different:http://jqueryui.com/demos/autocomplete/#default
Anyways if you're trying to the do the same thing as the question asks, there is no more parse function, as far as I know there is no function that is called with the search results.
The way I managed to pull this off is by overriding the autocomplete's filter function - Note: this will affect all your autocompletes
$.ui.autocomplete.filter = function(array, term) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
var aryMatches = $.grep( array, function(value) {
return matcher.test(value.label || value.value || value);
});
if (aryMatches.length == 0){
aryMatches.push({
label: '<span class="info" style="font-style: italic;">no match found</span>',
value: null
});
}
return aryMatches;
};
The function is slightly modified from the source, the grep call is the same, but if there are no results I add an object with a value of null, then I override the select calls to check for a null value.
This gives you an effect where if you keep typing and no matches are found you get the 'no matches found' item in the dropdown, which is pretty cool.
To override the select calls see jQuery UI Autocomplete disable Select & Close events
$(this).data('autocomplete').menu.options.selected = function(oEvent, ui){
if ($(ui.item).data('item.autocomplete').value != null){
//your code here - remember to call close on your autocomplete after
}
};
Since I use this on all my autocompletes on a page, make sure you check if value is null first! Before you try to reference keys that aren't there.
You could try supplying a parse option (function to handle data parsing) and do what you need when no results are returned to parse.
This example assumes you're getting back an array of JSON objects that contain FullName and Address attributes.
$('#search').autocomplete( {
dataType: "json",
parse: function(data) {
var array = new Array();
if (!data || data.length == 0) {
// handle no data case specially
}
else {
for (var i = 0; i < data.length; ++i) {
var datum = data[i];
array[array.length] = {
data: datum,
value: data.FullName + ' ' + data.Address,
result: data.DisplayName
};
}
}
return array;
}
});
I'm using the following code for the same purpose (the message is shown in the autocomplete list):
success: function(data, status, xhr){
if(!data.length){
var result = [
{
label: 'There are no matches for your query: ' + response.term,
value: response.term
}
];
response(result);
}
else{
// normal response
}
}
You can also utilize the "response" event to examine this. Simple but powerful. http://api.jqueryui.com/autocomplete/#event-response
response: function (event, ui) {
if (ui.content.length == 0) {
//Display an alert or something similar since there are no results
}
},

Categories

Resources