I have an observable array that I am capturing from the controller , its bringing out out the whole object when I use ko.mapping from js , how can I access an array element from the objects . At the moment it returns somethings"{"driverId":1,"driverName":"Simon Jenkins",}" how do I pick out just the name and not the ID or vice versa
if (!pageViewModel.isAuthenticated()) return;
$.when(getSecureData("/api/vehicleDrivers/" + id))
.done(function (driverList) {
driverList.unshift({ "driverId": 0, "driverName": "Please select a driver..." });
pageViewModel.DriverVM.driverList(driverList);
pageViewModel.vehicleVM.driverDetail.driverId(ko.mapping.fromJS(driverList));
/*var List = driverList;
List[0] = pageViewModel.VehicleVM.driverDetail.driverId;
List[1] = pageViewModel.vehicleVM.driverDetail.driverName;*/
})
.fail(function (message) {
$.msgbox(message);
});
}
If you want to ignore some properties when mapping, you can use the ignore option. If you want to specify which fields are included, you can preprocess with ko.utils.arrayMap
var driverIdList = ko.utils.arrayMap(driverList, function (item) {
return item.driverID;
});
Then you could use ko.mapping to convert that to observables, or just pass it to an observableArray.
Related
I have a list of html elements with data attributes, which I would like to assemble into a jQuery object and manipulate the values.
What is the best way to dynamically add these in an each loop so that I can easily access the data as so: data.name and data.name.prop?
I want all the naming conventions to be dynamic and based on the data.
I based my code on the top answer from here: How to create dynamically named JavaScript object properties?
So far I have:
$('.licences-list .data div').each(function(index) {
var data = {}
cats[$(this).find('p').data('cat')] = $(this).find('p').data('catname')
cats.push(data)
})
But when I try to iterate over the data array, like so:
$.each(cats, function(key, value){
$('<div class="card"><p>'+value+'</p></div>').appendTo('#commercial-licenses');
});
I just get [object Object] output... and I'm not sure why!
var data = {}
cats[$(this).find('p').data('cat')] = $(this).find('p').data('catname')
Each time you loop through, you're actually just adding an empty object (data) to your array (cats). You're then assigning a named property to that array (cats) which $.each has no idea about (it ignores them because it's iterating over an actual array).
My guess is you want an object map which is something like: var cats = { "f1": "feline 1", "f2": "feline " };
In that case what you want is:
var cats = {};
$('.licences-list .data div').each(function(index) {
cats[$(this).find('p').data('cat')] = $(this).find('p').data('catname')
})
If you want an array that contain more values than just strings (or whatever data you have added to the element), you create new objects each time and append them to the cats array:
var cats = [];
$('.licences-list .data div').each(function(index) {
cats.push({
'id': $(this).find('p').data('cat'),
'name': $(this).find('p').data('catname')
});
})
This will then give you an array that you can use $.each over, and access the values using: value.id, value.name
Don't over complicate it.
$('.div').attr('data-attribute', 'data-value');
using your example:
$('.licences-list .data div').attr('attribute-name', 'attribute-value');
My Json is like this:
[
{"isoCode":"BW","name":"Botswana ","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BR","name":"Brazil ","CashOut":"Y","BankOut":"Y","MMT":null},
{"isoCode":"BG","name":"Bulgaria ","CashOut":"Y","BankOut":"Y","MMT":"Y"},
{"isoCode":"BF","name":"Burkina Faso","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BI","name":"Burundi","CashOut":"","BankOut":"","MMT":"Y"},
{"isoCode":"KH","name":"Cambodia","CashOut":"Y","BankOut":"","MMT":null}
]
I want all the names which have BankOut value as "Y" into an array using JavaScript, in order to use those names in my protractor automation.
You need to use filter method of array. It takes function as it argument. And runs it against each element of array. If function returns true (or other truthy value) then that element stays in newly created array.
var list =[ {"isoCode":"BW","name":"Botswana ","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BR","name":"Brazil ","CashOut":"Y","BankOut":"Y","MMT":null},
{"isoCode":"BG","name":"Bulgaria ","CashOut":"Y","BankOut":"Y","MMT":"Y"},
{"isoCode":"BF","name":"Burkina Faso ", "CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BI","name":"Burundi","CashOut":"","BankOut":"","MMT":"Y"},
{"isoCode":"KH","name":"Cambodia","CashOut":"Y","BankOut":"","MMT":null}
];
var onlyBankOutY = list.filter(function (item) {
return item.BankOut === 'Y';
});
document.body.innerHTML = onlyBankOutY.map(function (item) {
return JSON.stringify(item);
}).join('<br>');
var list =[
{"isoCode":"BW","name":"Botswana ","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BR","name":"Brazil ","CashOut":"Y","BankOut":"Y","MMT":null},
{"isoCode":"BG","name":"Bulgaria ","CashOut":"Y","BankOut":"Y","MMT":"Y"},
{"isoCode":"BF","name":"Burkina Faso ", "CashOut":"Y","BankOut":"","MMT":null}, {"isoCode":"BI","name":"Burundi","CashOut":"","BankOut":"","MMT":"Y"},
{"isoCode":"KH","name":"Cambodia","CashOut":"Y","BankOut":"","MMT":null}
];
var names = [];
list.forEach(function(el) {
if (el.BankOut === 'Y') {
names.push(el.name)
}
})
In parse I have a class named "TestScore". Each object has a key named "quizName".
I need to get an array of unique "quizName" values. I wrote the below which queries the "TestClass" and loops through the results looking for unique "quizName" values.
At first seemed to do the job. But then I realized that the maximum number of returned objects is 1000. Soon there will be more than 1000 objects stored which means that this method will not guarantee that I end up will all values.
function loadTests(){
//create an array to hold each unique test name as we find them
var uniqueEntries = [];
//query parse to return TestScore objects
var TestScore = Parse.Object.extend("TestScore");
var query = new Parse.Query(TestScore);
query.limit(1000) //added this after realizing that the default query limit is only 100
query.find({
success: function(testScore) {
$(testScore).each(function(index, score) {
//here I loop though all of the returned objects looking at the "quizName" for each
if($.inArray(score.get("quizName"), uniqueEntries) === -1) {
//if the quiz name is not already in the "uniqueEntries" array, I add it to the array
uniqueEntries.push(score.get("quizName"));
}
});
//do stuff with quiznames here...., add them as options in select boxes mostly
}
});
}
I looked at {Parse.Query} notContainedIn(key, values) which looks promising but cant figure out if I can add values to the array as I find them. It seems like I would have to have an array to start with (defeating the whole point.)
This part of the docs "{Parse.Query} Returns the query, so you can chain this call." makes me think I might be able to chain queries together to get what I need, but that doesn't seem very efficient.
How can I retrieve unique values for key "quizName" when my class has > 1000 objects?
I'm sure you're long past this by now, but only way I know of to do it is to use one query after another by using a .skip(#) value for each query. So get 1000, then query again with .skip(1000), concatenate the items from the first list and second, then query again with .skip(2000), etc...
Be aware that I think there's a limit on skip values of 10,000. Don't take my word on that, just pointing you to something that I think is right that you should confirm if you think it applies to your situation.
I eventually found a tutorial online that I was able to modify and came up with the below. This effectively sets the return limit to 10,000 instead of 1,000 and allows setting several different parameters for the query.
My changes could surely be written better, maybe as an options object or similar but it works for my needs.
You can see a working demo here
function getStuff(){
// here we will setup and call our helper functions with callbacks to handle the results
var scheme =['SOTest',true]; // return all objects with value `true` in the `SOTest` column
// var scheme =['descending','createdAt']; // return all objects with sort order applied
// var scheme =''; // or just return all objects
// see `findChunk()` below for more info
var Remark = Parse.Object.extend("Remark");
schemePromise(Remark, scheme).done(function (all) {
console.log('Found ' + all.length+' Remarks');
$.each( all, function(i, obj){
$('#test').append(obj.get('Remark') +'<br>');
});
})
.fail(function (error) {
console.log("error: " + JSON.stringify(error));
});
}
getStuff(); // call our function
// helper functions used to get around parse's 1000 query limit
// raises the limit to 10,000 by using promises
function findChunk(model, scheme, allData) {
// if `scheme` was an empty string, convert to an array
// this is the default and returns all objects in the called class
if(scheme==''){ ['scheme',''] };
// will return a promise
var limit = 1000;
var skip = allData.length;
var findPromise = $.Deferred();
var query = new Parse.Query(model);
// to get all objects from the queried Class then sort them by some column
// pass `scheme` as an array like [ sort method, column to sort ]
if (scheme[0]=='descending') query.descending(scheme[1]);
else if (scheme[0]=='ascending') query.ascending(scheme[1]);
// to limt results to objects that have a certain value in a specific column
// pass `scheme` as an array like [ column name, value ]
else query.equalTo(scheme[0], scheme[1]);
// more options can easily be built in here using `scheme`
query
.limit(limit)
.skip(skip)
.find()
.then(function (results) {
findPromise.resolve(allData.concat(results), !results.length);
}, function (results) {
findPromise.reject(error);
});
return findPromise.promise();
}
function schemePromise(model, scheme, allResults, allPromise) {
// find a scheme at a time
var promise = allPromise || $.Deferred();
findChunk(model, scheme, allResults || [])
.done(function (results, allOver) {
if (allOver) {
// we are done
promise.resolve(results);
} else {
// may be more
schemePromise(model, scheme, results, promise);
}
})
.fail(function (error) {
promise.reject(error);
});
return promise.promise();
}
I have used an ajax call to retrieve data from Googles places api and I have used a for/in loop to begin to pull the information. the information that I am looking for logs to the console, but I cannot get it to display in an array how I would like it to.
Right now I am getting a list of names when I request names which is a parameter in the JSON object. Is there a way to get it into an array so the I can randomly select one of the values from the array?
at this point the way it is returning my data, when I run a script to pull a random string, it pulls a random letter out of the last value to be found when searching through my JSON object.
Here is my code. Not sure if I explained myself clearly but it's the best that I could word what I am looking to do. Thanks.
// **GLOBAL VARIABLES** //
// Chosen Restaurant display area
var display = document.getElementById('chosenVenue');
// Grab button
var button = document.getElementById('selectVenue');
// Sample Array that gets queried
var venueData = ["McDonalds", "Burger King", "Wendys"];
// Grab JSON data from Google
$(document).ready(function(){
$.ajax({
url: 'hungr.php', // Send query through proxy (JSONP is disabled for Google maps)
data: { requrl: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.7484,-73.9857&radius=800&sensor=false&keyword=restaurants,food&key=AIzaSyBkCkXIHFjvqcqrRytSqD7T_RyFMNkR6bA&callback=?"}, // URL to query WITH parameters
dataType: "json",
type: "GET", // or POST if you want => update php in that case
success: function (data) {
// Traverse the array using for/in loop using i as var
for (var i in data.results) {
var results = data.results[i];
var nameResults = results.name;
console.log(nameResults);
var typesResults = results.types;
console.log(typesResults);
var vicinityResults = results.vicinity;
console.log(vicinityResults);
};
// On button click, randomly display item from selected array
button.addEventListener('click', function () {
console.log('clicked');
display.style.display = 'block';
//display.innerHTML = nameResults[Math.floor(Math.random() * nameResults.length)];
display.innerHTML = nameResults.toString() + "<br />" + vicinityResults.toString();
});
console.log('It is working');
},
error: function (request, status, error) {
console.log('It is not working');
}
});
});
Right now I am getting a list of names when I request names which is a parameter in the JSON object. Is there a way to get it into an array so the I can randomly select one of the values from the array?
Use the push method and a non-local variable:
this.nameResults = this.nameResults ? this.nameResults.push(results.name) : [];
then reference that with the Math.random method:
this.randName = function(){ return this.nameResults[Math.random() * this.nameResults.length | 0] };
References
Using Math.random flexibly
JavaScript: fast floor of numeric values using the tilde operator
I am trying to filter an array by omitting users that are already in a previous list:
FullList: Tom, Tim, Jim, Jill
UsersList: Tom, Jill
and with the help of another member I was able to use this array filter but the problem is that the filter result is the same as the usersList: Tom, Jill and i want the filter result to be Tim, Jim
var viewModel = function(data){
var _self = {};
var FullUsers = ko.observableArray([]);
var Users = ko.observableArray([]);
_self.UsersList = function(data){
$.each(data, function(index, user) {
_self.Users.push(new userViewModel(user));
}
}
_self.FullList = function(data){
$.each(data, function(index, user) {
_self.FullUsers.push(new userViewModel(user));
}
}
this._FilteredUsers=ko.computed(function() {
return ko.utils.arrayFilter(_self.FullUsers(), function(item) {
return ko.utils.arrayIndexOf(_self.Users(), item)<0;
});
});
}
I have two different get methods one for getting users and the other for full users - they are both the same the only difference is the id I pass in to one and the other doesn't require a passed id.
View Data-bind
<div data-bind="foreach: _FilteredUsers">
<span data-bind="text: Name"></span>
</div>
how can i alter the code so my result is Tim, Jim?
Current results based off above code - i get FullUsers including the once I don't want to show. when I flip the Users() and FullUsers() I am only getting Users list
You'll need to search the Users ObservableArray for a matching item using arrayFirst (returns true if any of the filter function returns true). Since you want users in the full list that are NOT in the normal list, you add a ! to the arrayFirst. If the attribute to filter on is an observable, make sure to add () to the end of the attribute.
this._FilteredUsers=ko.computed(function() {
return ko.utils.arrayFilter(_self.FullUsers(), function(fuitem) {
return !ko.utils.arrayFirst(_self.Users(), function(item) {
return fuitem.Name() === item.Name(); //replace .Name with the attribute you want to match on
});
});