Knockout Js Array.removeAll() not working - javascript

var x=ko.observableArray([....]);
x.removeAll();
Situation is 'x' is holding the selected values from dropdowns which are dynamically generated using knockout. I want to clear all the selections made by the user.
The above code is not working in my situation, so i have to 'undefine' each element in the array using a for loop - which is a very bad way(i feel). i want to know if there any better way of doing this?
I also tried this:
x([]);
Which didn't work either.
My code Looks something like this
var data_Main = [
{[a,b,c] },{[d,e,f]},{[g,h,i]}
];
var selectedKoArray= ko.observableArray([]);
var Lst=ko.observableArray([
{Txt: 'aaa', Val: 'a'},
{Txt: 'bbb', Val: 'b'},
{Txt: 'ccc', Val: 'c'}
]);
var dataArray = ko.observableArray([Lst:Lst(), Lst:Lst1(), Lst:Lst2()]);
var selectedHFilters = ko.observableArray([]);
for (var i = 0; i < dataArray.length - 1; i++) {
if (selectedKoArray[i])
selectedKoArray[i] = undefined;
}
-----------------------------------------------------HTML-------------------------------
<div data-bind="foreach:dataArrayKO ">
<select class="select2-offscreen filter-select" data-bind="options:Lst, optionsText: 'Txt', optionsValue: 'Val', optionsCaption: '-Select-', value:$root.selectedHFilters[$index()]"></select>
</div>

This is not valid Javascript and will error, which may be the root of your problem:
var dataArray = ko.observableArray([Lst:Lst(), Lst:Lst1(), Lst:Lst2()]);
I suspect you wanted something like this (though Lst(), Lst1() and Lst2() are not defined in the code you've supplied, again this will error).
var dataArray = ko.observableArray([Lst.Lst(), Lst.Lst1(), Lst.Lst2()]);
The KO code for removing elements you have supplied is fine.

Related

Bind ng-options in ng-model on loading (like a bidirectional binding)

The situation:
I have the following select:
<select ng-model="model" ng-options="o as o.name for o in options track by o.code">
<option value="">- Default -</option>
</select>
My options datas are like this:
$scope.options = [{id: 1, code: 'foo', name: 'Foo!'}, {id: 2, code: 'bar', name: 'Bar!'}];
What I want to do:
I want to have my select with a pre-selected value. My constraint is that I only know the code attribute of my object. With the help of the track by notation I can do that simply like this:
$scope.model = {code: 'bar'};
And it works, the selected value of the select is "Bar!"
The problem:
When I send this data to my backend, I need to send the id attribute of my object. The data sent is {code: 'bar'} but not {id: 2, code: 'bar', name: 'Bar!'} as I want.
For me it is the normal behavior... because I stored in my model {code: 'bar'} and I did not change the value selected.
The conclusion:
Is there a way to tell to AngularJS to copy the value from the options list to model when there is a default value in model (when there is a match using the track by notation) ?
Info: I know that I can do something like this $scope.model = $scope.options[2] (with some logic to determine the index...) but I would like something more magical... If it is possible... :D
OP Info: I know that I can do something like this $scope.model = $scope.options[2] (with some logic to determine the index...) but I would like something more magical... If it is possible... :D
I have 3 magic's for your 3 objects
Magic 1 :
$scope.model = $scope.options.filter(function(item) {
return item.code=== 'bar';
})[0];
Magic 2:
app.filter('getById', function() {
return function(input, id) {
var i=0, len=input.length;
for (; i<len; i++) {
if (+input[i].id == +id) {
return input[i];
}
}
return null;
}
});
$scope.model = $filter('getById')($scope.options, 2);
Magic 3
angular.forEach($scope.options, function(option) {
$scope.model = option.name == "name";
if($scope.model !=null){break}
});
You need to add a ng-change on the <select> and then create a function that will look for the selected option and its corresponding JSON model. Use this
HTML
<div ng-app='app' ng-controller='mainCtrl'>
<select ng-model="model" ng-options="o as o.name for o in options track by o.code"
ng-change='getValue(this)'>
<option value="">- Default -</option>
</select>
</div>
CONTROLLER
angular.module('app',['QuickList']).controller('mainCtrl', function($scope){
$scope.options = [{id: 1, code: 'foo', name: 'Foo!'}, {id: 2, code: 'bar', name: 'Bar!'}];
$scope.model = {code: 'bar'};
$scope.getValue = function(item){
console.log($scope.selectedOption = item.model);
}
});
Whenever you will select the option in the <select> box you will see the actual JSON object for that option printed in the console.
Here is the working JSFIDDLE

Grouping / counting in javascript using underscore.js

I am new to javascript (and to Stack Overflow) and I've encountered a problem I can't seem to solve. I am trying to generate a simple pie chart that shows the number of Projects for each value of Technology in my data. This is the kind of data I am working with:
[Project1, Java]
[Project2, Excel]
[Project3, SAS]
[Project4, Java]
The pie ratio in the example above would be 2:1:1.
The first part of my code loads the data and pushes it to an array, "techArray", that contains [project, tech]. This part works ok - I've verified it in a simplified version of the code.
I then want to group the array "techArray" and count the instances of each tech. To do so I'm using the Underscore library, as follows:
var chartData = [];
var techData = _.groupBy(techArray, 'tech');
_.each(techData, function(row) {
var techCount = row.length;
chartData = push( {
name: row[0].tech,
y: techCount
});
});
The script then renders the chartData array using highcharts. Again, I have verified that this section works using a simplified (ungrouped) version.
There must be an issue with the grouping/counting step outlined above because I am seeing no output, but I simply can't find where. I am basing my solution on the following worked example: Worked example.
If anyone can spot the error in what I've written, or propose another way of grouping the array, I'd be very grateful. This seems like it should be a simpler task than it's proving to be.
countBy could be used instead of groupBy:
var techArray = [
{ project: 'Project1', tech: 'Java'},
{ project: 'Project2', tech: 'Excel'},
{ project: 'Project3', tech: 'SAS'},
{ project: 'Project4', tech: 'Java'},
];
var counts = _.countBy(techArray,'tech');
This will return an object with the tech as properties and their value as the count:
{ Java: 2, Excel: 1, SAS: 1 }
To get the data in the form for highcharts use map instead of each:
var data = _.map(counts, function(value, key){
return {
name: key,
y: value
};
});
This should work
var techArray = [['Project1','Java'], ['Project2', 'excel'], ['Project3', 'Java']];
var chartData = [];
var techData = _.groupBy(techArray, function(item) {
return item[1];
});
_.each(techData, function(value, key) {
var techCount = value.length;
chartData.push({
name: key,
y: techCount
});
});
_.groupBy needs to either get a property name, or a function that returns the value being grouped. There is no tech property of an array, so you cant group by it. But, as our techArray is an array of tuples, we can pass a function _.groupBy that returns the value that we want to groupBy, namely the second item in each tuple.
chartData now looks like this:
[{
name: 'Java',
y: 2
}, {
name: 'excel',
y: 1
}]

angularjs ng-model and ng-select strange behaviour

I have a list of persons objects that I want to bind to a select element.
Controller implementation:
// Person controller
function PersonCtrl($scope) {
$scope.persons = [{id: 1, name: 'alex'}, {id: 2, name: 'jhon'}];
$scope.selectedPerson = {id: 2, name: 'jhon'};
}
Html markup:
<select ng-model="selectedPerson" ng-options="p.name for p in persons"></select>
The problem is that the binding seems to work only from the HTML to the scope and not the other way around. If I select an item from the drop down, it will correctly update the $scope.selectedPerson. But, if I initially set the value of the $scope.selectedPerson variable to one of the objects in the persons list, the value will not be reflected on the select control.
I also have fiddle that shows exactly what the problem is: http://jsfiddle.net/nE3gt/
Thank you in advance!
You need to set the selectedPerson to an element in the persons array, not a new object - otherwise Angular has no idea they are the same thing.
// Person controller
function PersonCtrl($scope) {
$scope.persons = [{id: 1, name: 'alexx'}, {id: 2, name: 'jhon'}];
$scope.selectedPerson = $scope.persons[1];
$scope.submit = function () {
//console.log(JSON.stringify($scope.Person));
$("#obj").text(JSON.stringify($scope.Person));
};
}
Updated fiddle: http://jsfiddle.net/nE3gt/2/
edit
If I'm understanding you correctly, you want to do something along these lines:
// Person controller
function PersonCtrl($scope) {
//serverData is the result of some http request...
var serverData = {persons: [{id: 1, name: 'alexx'}, {id: 2, name: 'jhon'}], selectedPerson: {id: 2, name: 'jhon'}};
$scope.persons = serverData.persons;
$scope.selectedPerson = null;
//find obj in persons that equals selectedPerson
for(var i = 0, l = serverData.persons.length; i < l; i++)
{
if(serverData.persons[i].id === serverData.selectedPerson.id)
{
$scope.selectedPerson = serverData.persons[i];
}
}
$scope.submit = function () {
//console.log(JSON.stringify($scope.Person));
$("#obj").text(JSON.stringify($scope.Person));
};
};
Even if your data comes back as different objects you need to make sure you're setting selectedPerson to an item that is in the persons array.
new fiddle: http://jsfiddle.net/nE3gt/4/
Set it to the index of the array you're binding to:
$scope.selectedPerson = $scope.persons[0];
Demo: http://jsfiddle.net/nE3gt/3/

Use arrayvalues to access (sub)arrays

I have a page where I want to see if a certain value exists in one of the arrays I have defined, there is one main array and several "sub" arrays, they are defined like this:
var main = ['header', 'firstname', 'surname', 'tel'];
var firstname_label = ['Hank', 'Dave', 'Erin', 'Jessica'];
var surname_label = ['Michaels', 'McHankering', 'Jameson', 'Lloydd', 'Eagon', 'Philips'];
var tel_label = ['mobile', 'landline'];
I want to check the sub arrays with a variable I have, I was thinking something along these lines:
for (i=1;i<=mainCount;i++)
{
jQuery.inArray(var_x, main[i]_label)
}
Is something like this possible?
Try using an Object:
var main = ['header', 'firstname', 'surname', 'tel'];
var sub =
{
firstname_label: ['Hank', 'Dave', 'Erin', 'Jessica'],
surname_label: ['Michaels', 'McHankering', 'Jameson', 'Lloydd', 'Eagon', 'Philips'],
tel_label: ['mobile', 'landline']
};
for (i=1;i<=mainCount;i++)
{
jQuery.inArray(var_x, sub[main[i] + '_label'])
}
The alternative would be to use eval to select the variable name, but don't go there.

Using jQuery.data to store a list of items

I'm working on a page where I need to associate a list of objects with a row of a table, and I'm using jQuery.
jQuery.data seems to just associate a piece of data with a key, whereas I need more like
id=4,setting=2
id=3,setting=1
...
I don't know how long the list could be, and it could be empty.
Is there a sensible way of doing this?
You can store anything as jQuery data, so you could do this:
var myData = [ { id: 4, setting: 2 }, [ id:3, setting:1 ] };
$("#myitem").data("mydata", myData);
If you want to select something by id, you could do this:
var myData = {};
myData[4] = 2;
myData[3] = 1;
$("#myitem").data("mydata", myData);
Then you can access your settings like this:
var value = $("#myitem").data("mydata")[3]; // returns 1
I haven't got a great amount of time to try it now, but instead of storing a simple string against the key, why not store an object against it?
To paraphrase the jquery docs...
$("div").data("blah", {id: 4,setting: 2});
var myBlah = $("div").data("blah");
var id = myBlah["id"];
var setting = myBlah["setting"];
Let me know how you get on.
You can use arrays to store lists and JSON objects to store key-value pairs.
<div id="DIV1"></div>
<div id="DIV2"></div>
<div id="DIV3"></div>
<div id="DIV4"></div>
<table><tbody><tr id="TR1"><td><td/></tr></tbody></table>
<script type="text/javascript">
$(function() {
$("#TR1").data("blah", [{id: 4, setting: 2}, {id: 3, setting: 1}]);
$("#DIV1").text($("#TR1").data("blah")[0].id);
$("#DIV2").text($("#TR1").data("blah")[0].setting);
$("#DIV3").text($("#TR1").data("blah")[1].id);
$("#DIV4").text($("#TR1").data("blah")[1].setting);
});
</script>

Categories

Resources