With knockout.js how to refresh observable array in a Select element - javascript

When the dropdown is loaded the items are populated correctly. But when I click the Refresh button the Dropdown items are not refreshed. The data binding isn't working on clicking the Refresh button. After clicking the Refresh button I am expecting to see 'Mary' and 'Sandra'.
Here's the JavaScript:
$(function () {
function viewModel() {
var self = this;
self.persons = ko.observableArray([]);
self.persons.push({
id: 1,
name: 'John'
});
self.persons.push({
id: 2,
name: 'Paul'
});
self.refreshPersonList = function () {
self.persons = ko.observableArray([]);
self.persons.push({ id: 3, name: 'Mary' });
self.persons.push({ id: 4, name: 'Sandra' });
};
}
ko.applyBindings(new viewModel());
});
And HTML:
<select data-bind="options: $root.persons(), optionsValue: 'id', optionsText: 'name'"></select>
<button value="Refresh" data-bind="event: {click : $root.refreshPersonList() }">Refresh Person List</button>

Here you are creating a new array, breaking existing bindings:
self.persons = ko.observableArray([]);
Try emptying the array instead:
self.refreshPersonList = function () {
self.persons.removeAll(); //Empty array
self.persons.push({ id: 3, name: 'Mary' });
self.persons.push({ id: 4, name: 'Sandra' });
};

Related

How to auto select users state in data-bind options select in Knockout

i have a drop down of states and their ID:
<select data-bind="options: States, optionsText: 'text', value: SelectedState"></select>
Javascript
function ViewModel() {
this.States = ko.observableArray(states);
this.SelectedState = ko.observable(usersState);
};
var states = [
{ value: 10, text: "California" },
{ value: 3, text: "New York" },
{ value: 9, text: "Florida" }
];
ko.applyBindings(new ViewModel());
usersState is a variable that may or maynot contain the users info. By default its null. But if the user has already logged in then it should populate with the users selected state. For this example, the users has logged in and their select state is 9 for florida.
so i declared usersState = 9; at the top.
What i am trying to do is simply auto select Florida in the drop down based on the users info.
not sure why its not selecting it. Here is my fiddle: http://jsfiddle.net/neosketo/sw9dzjk1/2/
The SelectedState refers to a state object. Your initial selection is a number. You'll have to find the state object corresponding to the number:
var usersState = 9;
// This method finds an object by value property
var findStateById = function(states, id) {
return states.find(function(state) {
return state.value === id;
});
};
function ViewModel() {
this.States = ko.observableArray(states);
// In this example, SelectedState is an object with a value and text property
this.SelectedState = ko.observable(findStateById(states, usersState));
};
// Test data
var states = [{
value: 10,
text: "California"
}, {
value: 3,
text: "New York"
}, {
value: 9,
text: "Florida"
}];
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: States, optionsText: 'text', value: SelectedState"></select>
(Note that I used Array.prototype.find which isn't supported by all browsers)
Alternatively, you could use the optionsValue option to tell knockout to use the value property to match selection to options. Personally, I prefer using the actual object: knockout being able to work with references to real instances rather than using strings makes developing easier.
var usersState = 9;
function ViewModel() {
this.States = ko.observableArray(states);
// In this example, SelectedState is a number
this.SelectedState = ko.observable(usersState);
};
var states = [{
value: 10,
text: "California"
}, {
value: 3,
text: "New York"
}, {
value: 9,
text: "Florida"
}];
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: States,
optionsText: 'text',
optionsValue: 'value',
value: SelectedState"></select>

AngularJS: Using ng-selected to select multiple options, based on collection

I have two arrays of objects, one array being a subset of the other:
$scope.taskGroups = [
{id: 1, name: 'group1', description: 'description1'},
{id: 2, name: 'group2', description: 'description2'},
{id: 3, name: 'group3', description: 'description3'}
];
$scope.selectedGroups = [
{id: 1, name: 'group1', description: 'description1'},
{id: 2, name: 'group3', description: 'description3'}
];
After unsuccessfully trying to get my head around using ng-option, I thought that I could perhaps create a function to determine if an option should be selected in the select list, based on what I picked up in the documentation:
ngSelected
- directive in module ng Sets the selected attribute on the element, if the expression inside ngSelected is truthy.
So, I came up with this function:
$scope.inSelectedGroups = function(taskGroup) {
angular.forEach($scope.selectedGroups, function(group) {
if (taskGroup.id == group.id) {
return true;
}
return false;
});
};
and tried to use it in this html:
<select multiple ng-model="selectedGroups" style="width: 100%" size="7">
<option ng-repeat="taskGroup in taskGroups" value="{{taskGroup.id}}" ng-selected="inSelectedGroups(taskGroup)">{{taskGroup.name}}</option>
</select>
but, no dice - the full list of taskGroups shows, but the selectedTaskGroups aren't, well, selected...
Am I barking up the wrong tree here?
the full list of taskGroups shows, but the selectedTaskGroups aren't,
well, selected.
I tried your solution which is using the ngSelected attribute but I was unsuccessful as well so I tried using the ngOptions instead and it works.
angular.module('app', []).controller('TestController', ['$scope',
function($scope) {
$scope.taskGroups = [{
id: 1,
name: 'group1',
description: 'description1'
}, {
id: 2,
name: 'group2',
description: 'description2'
}, {
id: 3,
name: 'group3',
description: 'description3'
}];
$scope.selectedGroups = [{
id: 1,
name: 'group1',
description: 'description1'
}, {
id: 2,
name: 'group3',
description: 'description3'
}];
}
])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestController">
<select multiple="true" ng-model="selectedGroups" style="width: 100%" ng-options="taskGroup.id as taskGroup.description for taskGroup in taskGroups track by taskGroup.id" size="7">
</select>
</div>
See carefully, you are returning Boolean value from function defined in angular.forEach parameter and so nothing is returned from inSelectedGroups function
Try modifying your function to:
$scope.inSelectedGroups = function(taskGroup) {
var flag = false;
angular.forEach($scope.selectedGroups, function(group) {
if (taskGroup.id == group.id) {
flag = true;
return;
}
flag = false;
return;
});
return flag;
};

How to filter select-box in devextreme

I'm having some problems to filter with 03 select boxes, country, state and city.
How can I get select boxes nested?
And How can I get some filter with these data?
My code in script.js using MySQL Database:
var serviceFilterCountry = "http://localhost:8000/filtercountry";
var serviceFilterProvince = "http://localhost:8000/filterprovince";
var serviceFilterCity = "http://localhost:8000/filtercity";
$scope.countries = new DevExpress.data.DataSource(serviceFilterCountry);
$scope.provinces = new DevExpress.data.DataSource(serviceFilterProvince);
$scope.cities = new DevExpress.data.DataSource(serviceFilterCity);
//var dataSourceCity = new DevExpress.data.DataSource(serviceFilterCity);
//var dataSourceF = new DevExpress.data.DataSource(serviceFilter);
$scope.selectedProvince = null;
$scope.filterProvincesByCountry = function(e) {
var countryP = e.value;
$scope.provinces.filter("country", countryP);
$scope.provinces.load().done(function(result) {
$scope.selectedProvince = result.state;
});
};
$scope.selectedCity = null;
$scope.filterCitiesByProvince = function(e) {
var provinceC = e.value;
$scope.cities.filter("country", $scope.countries.select('country'));
$scope.cities.filter("state", provinceC);
$scope.cities.load().done(function(result) {
$scope.selectedCity = result.city;
});
};
To filter data by a selectbox value you can use the onValueChanged event. For example, the following code shows how to filter cities by country id:
JS:
$scope.countries = new DevExpress.data.DataSource({
store: [{id: 1, text: "USA"}, {id: 2, text: "Canada"}]
});
$scope.cities = new DevExpress.data.DataSource({
store: [{id: 1, countryId: 1, text: "NY"}, {id: 2, countryId: 2, text: "Toronto"}]
});
$scope.filterCitiesByCountry = function(e) {
var countryId = e.value;
$scope.cities.filter("countryId", countryId);
$scope.cities.load();
};
HTML:
<div dx-select-box="{dataSource: countries, displayExpr: 'text', valueExpr: 'id', onValueChanged: filterCitiesByCountry}"></div>
<div dx-select-box="{dataSource: cities, displayExpr: 'text', valueExpr: 'id', bindingOptions: { value: 'selectedCity' } }"></div>
More information about the filter operation you can find here.
I've create a small sample that demonstrates this approach in action - http://plnkr.co/edit/SR93AIRSp9TUuA5fYmpa

How can I call different functions based on the value when a <select> value changes?

I want to call different function on changing the select option
Here is the markup:
<p>With every selection change I want a different function to be called</p>
<select data-bind="options: availableMeals, optionsText: 'name', value: selectedMeal, optionsValue: 'value', event: {change: onChange}">
</select>
Here is my viewmodel:
function ReservationsViewModel() {
var self = this;
self.availableMeals = ko.observableArray(
[
{name: "Standard (sandwich)", value: 0},
{name: "Premium (lobster)", value: 34.95},
{name: "Ultimate (whole zebra)",value: 290}
]
);
self.selectedMeal = ko.observable(self.availableMeals()[0]);
// i want this when i change to sandwitch
self.onChange = function() {
alert("for sandwitch");
};
// i want this when i change to lobster
self.onChange1 = function() {
alert("for lobster");
};
//i want this when i change to ultimate
self.onChange2 = function() {
alert("for whole zebra");
};
}
ko.applyBindings(new ReservationsViewModel());
I know that I have only bind the onChange function with change event. What could be the way to call three different functions on different selections?
Here is the demo fiddle: http://jsfiddle.net/mLv42zkL/
Use one function onChange and then call other functions depending on the value of selectedMeal.
For example:
function ReservationsViewModel() {
var self = this;
self.availableMeals = ko.observableArray(
[{
name: "Standard (sandwich)",
value: 0
}, {
name: "Premium (lobster)",
value: 34.95
}, {
name: "Ultimate (whole zebra)",
value: 290
}]
);
self.selectedMeal = ko.observable(self.availableMeals()[0]);
self.onChange = function() {
switch (self.selectedMeal()) {
case 0:
self.sandwichSelected();
break;
case 34.95:
self.lobsterSelected();
break;
case 290:
self.zebraSelected();
break;
}
};
self.sandwichSelected = function() {
alert("for sandwich");
};
self.lobsterSelected = function() {
alert("for lobster");
};
self.zebraSelected = function() {
alert("for whole zebra");
};
}
ko.applyBindings(new ReservationsViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<p>With every selection change I want a different function to be called</p>
<select data-bind="options: availableMeals, optionsText: 'name', value: selectedMeal, optionsValue: 'value', event: {change: onChange}">
</select>
Fiddle Demo

Why this knockout mapping code is not working?

I have a list of json objects which i want to map to knockout viewmodel list using ko mapping plugin. The below is my code (just to explain my problem, no need to take this code seriously):
var itemsList = [
{ Id: 1, Name: 'A' },
{ Id: 2, Name: 'B' },
{ Id: 3, Name: 'C' }
];
var item = function(data) {
ko.mapping.fromJS(data, {}, this);
}
var listOfItems = ko.observableArray();
var listOfItems = ko.mapping.fromJS(itemsList, {
create: function(options) {
return new item(options.data);
}
});
Now my listOfItems are always empty, why ??
You could really simplify this code and it is become working well.
var itemsList = [{ Id: 1, Name: 'A' }, { Id: 2, Name: 'B' }, { Id: 3, Name: 'C' }];
var viewModel = {
listOfItems: ko.mapping.fromJS(itemsList)
}
ko.applyBindings(viewModel);
Now you have viewModel with observableArray listOfItems, and all items in this array have Id and Name properties.
You can test it with folowing code:
<ul data-bind="foreach: listOfItems">
<li>
<span data-bind="text: Id"></span>
<span data-bind="text: Name"></span>
</li>
</ul>

Categories