Knockout update cell value in table - arrays

When I change selection in column B, the text in column A should change too, but not.
Why?
HTML:
<table>
<thead>
<tr>
<th style="width: 100px;">A</th>
<th style="width: 100px;">B</th>
</tr>
</thead>
<tbody data-bind="foreach: Data">
<tr>
<td><span data-bind="text: idOpt"></span></td>
<td><select data-bind="options: $root.MyOptions, optionsText: 'name', optionsValue: 'id', value: idOpt"></select></td>
</tr>
</tbody>
</table>
JS:
function AppViewModel() {
var self = this;
self.MyOptions = ko.observableArray([
{id: 'a1', name: 'One'},
{id: 'a2', name: 'Two'},
{id: 'a3', name: 'Three'}
]);
self.Data = ko.observableArray([
{idOpt: 'a1'},
{idOpt: 'a2'},
{idOpt: 'a1'}
]);
}
var vm = new AppViewModel();
ko.applyBindings(vm);
http://jsfiddle.net/bnowicki/CrVBr/2/
Please help.

You must declare the items in your Data array as observables if you want them to bind/update.
function AppViewModel() {
var self = this;
self.MyOptions = ko.observableArray([
{id: 'a1', name: 'One'},
{id: 'a2', name: 'Two'},
{id: 'a3', name: 'Three'}
]);
self.Data = ko.observableArray([
{idOpt: ko.observable('a1')},
{idOpt: ko.observable('a2')},
{idOpt: ko.observable('a1')}
]);
}
var vm = new AppViewModel();
ko.applyBindings(vm);
The Knockout documentation shows you the difference between using plain models, and then models with observables http://knockoutjs.com/documentation/observables.html

Related

ng-table data not showing

here my question:
I am trying to build a directive in angular, which would use an ng-table inside. I am using mocked data. The problem is that I cannot render data in the table. here is my directive:
;(function(app) {
app.directive('customTables', [
'NgTableParams',
function(NgTableParams) {
return {
restrict: 'E',
templateUrl: 'templates/directives/table_directive.html',
scope: {
},
link: function(scope) {
var dataset = [{
name: "Moroni50",
age: "50"
}, {
name: "Moroni49",
age: "49"
}];
scope.tableParams = new NgTableParams({}, {
data: dataset
});
}
};
}]);
})(app);
here is the html:
<table ng-table="tableParams" class="table table-bordered table-striped table-condensed">
<tr ng-repeat="user in $data">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">{{user.age}}</td>
</tr>
here is how I call it:
<custom-table></custom-table>
Any suggestions?
Replace
scope.tableParams = new NgTableParams({}, {
data: dataset
});
with
scope.tableParams = new NgTableParams({}, {
scope.data: dataset
});
and in html:
<tr ng-repeat="user in $data">
with
<tr ng-repeat="user in data">
Try this:
scope.data = [{
name: "Moroni50",
age: "50"
}, {
name: "Moroni49",
age: "49"
}];
scope.tableParams = new NgTableParams({}, {
data: scope.data
});
Try this instead
scope.tableParams = new NgTableParams({}, {
dataset: dataset
});

How get a label from a store in Angular while repeat another store

I've two stores in my controller:
$scope.categoryStore = [{id: 1, label: "A"}, {id: 2, label: "B"}, {id: 3, label: "C"}];
$scope.collectionStore = [{id: 1, categoryId: 1, name: "Test"}, {id: 1, categoryId: 2, name: "Test2"}];
In my view I have a ng-repeat for the collectionStore. Now I want to display the label of the categoryStore instead of the categoryId.
<tr ng-repeat="item in collectionStore">
<td>{{item.id}}</td>
<td>{{item.categoryid}} <!-- this would be the label --></td>
<td>{{item.name}}</td>
</tr>
My suggestion is to create a function to handle this and use the $filter within that function.
In your view:
<tr ng-repeat="item in collectionStore">
<td>{{item.id}}</td>
<td>{{getCategoryLabel(item.categoryId)}}</td> <!-- handle this with a function -->
<td>{{item.name}}</td>
</tr>
Then in your controller:
$scope.getCategoryLabel = function(categoryId) {
var category = $filter('filter')($scope.categoryStore, { id: categoryId }, true);
if (category.length) return category[0].label;
}

Angular - multiple ng repeat in table

[EDIT : Solved but i think there's a better way, if you find it, i'm still interested]
I have a list of banks.
Each bank contains a list of accounts.
Each accounts contains a list of operations.
I would like to display all the operations in a table.
Here's what the bank list looks like :
$scope.banks = [
{
id: 1,
name: 'bank_1',
accounts: [
{
id: 1,
name: 'account_1',
operations: [
{id: 1, name:'operation_1', price:100},
{id: 2, name:'operation_2', price:200},
{id: 3, name:'operation_3', price:300},
{id: 4, name:'operation_4', price:400}
]
},
{
id: 2,
name: 'account_2',
operations: [
{id: 5, name:'operation_5', price:100},
{id: 6, name:'operation_6', price:200},
{id: 7, name:'operation_7', price:300},
{id: 8, name:'operation_8', price:400}
]
}
]
},
{
id: 2,
name: 'bank_2',
accounts: [
{
id: 3,
name: 'account_3',
operations: [
{id: 9, name:'operation_9', price:100},
{id: 10, name:'operation_10', price:200},
{id: 11, name:'operation_11', price:300},
{id: 12, name:'operation_12', price:400}
]
},
{
id: 4,
name: 'account_4',
operations: [
{id: 13, name:'operation_13', price:100},
{id: 14, name:'operation_14', price:200},
{id: 15, name:'operation_15', price:300},
{id: 16, name:'operation_16', price:400}
]
}
]
}
];
In order to display that properly with Angular i wanted to make something like that :
<table>
<tr>
<th>Banque</th>
<th>Account</th>
<th>ID OP</th>
<th>Name</th>
<th>Price</th>
</tr>
<div ng-repeat="bank in banks">
<div ng-repeat="account in bank.accounts">
<div ng-repeat="operation in account.operations">
<tr>
<td>{{banque.name}}</td>
<td>{{account.name}}</td>
<td>{{operation.id}}</td>
<td>{{operation.name}}</td>
<td>{{operation.price}}</td>
</tr>
</div>
</div>
</div>
</table>
But i know it's not correct to break the table > tr > td.
After some researches, i think i may have to use the ng-repeat-start, ng-repeat-end directive but i don't understand how and i'm not even sure it's the good thing to do.
If you have any idea how to solve that i'd be glad to hear your solution.
This can be easily achieved by creating custom filter that will return the list of operation.
Filter
.filter('filterData', function(){
return function(data, firstParam, secondParam){
var returnData = [];
angular.forEach(data, function(value, index){
angular.forEach(value[firstParam], function(val, ind){
angular.forEach(val[secondParam], function(v, i){
returnData.push(v)
});
});
});
return returnData;
}
});
Markup
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
</tr>
<tr ng-repeat="operation in banks| filterData: 'accounts': 'operations'">
<td>{{operation.id}}</td>
<td>{{operation.name}}</td>
<td>{{operation.price}}</td>
</tr>
</table>
Working Plunkr Here
Hope this could help you, Thanks.
Thx you saved my day.
I enhance your solution because filterData function is running twice (for each element of $scope.banks array).
Prefers ng-init in tbody container of tr_ngrepeat.
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody ng-init="operationlist=(banks|filterData: 'accounts': 'operations')">
<tr ng-repeat="operation in operationlist">
<td>{{operation.id}}</td>
<td>{{operation.name}}</td>
<td>{{operation.price}}</td>
</tr>
</tbody>
</table>

AngularJS: On Change of Parent DropDown Option Also Changes the Dependant Drop Down Options Associated with Other Parents

Visit this Link to view the problem:
http://plnkr.co/edit/CPxvE4SC6ScTH57s6CmQ?p=preview
index.html*************************
<div ng-app="myApp">
<div ng-controller="myController">
<table>
<thead>
<th>Plan</th>
<th>Options</th>
</thead>
<tbody>
<tr ng-repeat="order_detail in order_details">
<td>
<select id="plan_id" name="plan_id" ng-model="order_detail.plan_id" ng-options="plan.plan_id as plan.name for plan in plans" required ng-change="loadPlanTemplates()">
<option value="">-- choose plan --</option>
</select>
</td>
<td>
<select id="plan_option_id" name="plan_option_id" ng-model="order_detail.plan_option_id" ng-options="plan_option.plan_option_id as plan_option.name for plan_option in plan_options" required ng-change="loadPlanTemplateValues()" >
<option value="">-- choose option --</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</div>
script.js******************************
var moduleMyAPP = angular.module('myApp', []);
moduleMyAPP.controller('myController', function ($rootScope, $scope, $http) {
$scope.order_details = [{plan_id: null, plan_option_id: null}, {plan_id: null, plan_option_id: null}, {plan_id: null, plan_option_id: null}];
$scope.plans = [{plan_id: 1, name: 'Gold'}, {plan_id: 2, name: 'Platinium'}, {plan_id: 3, name: 'Silver'}];
$scope.loadPlanTemplates = function () {
var planId = this.order_detail.plan_id;
switch (planId) {
case 1:
$scope.plan_options = [
{plan_option_id: 1, name: '10 Years'},
{plan_option_id: 2, name: '20 Years'},
{plan_option_id: 3, name: '30 Years'},
];
break;
case 2:
$scope.plan_options = [
{plan_option_id: 1, name: '5 Years'},
{plan_option_id: 2, name: '7 Years'},
{plan_option_id: 3, name: '9 Years'},
];
break;
case 3:
$scope.plan_options = [
{plan_option_id: 1, name: '2 Years'},
{plan_option_id: 2, name: '3 Years'},
{plan_option_id: 3, name: '4 Years'},
];
break;
}
}
});
`
You have several problems in your code.
You gave the same ID to each select, I changed it to be id="plan_id{{$index}}" so you could differentiate.
You used the same object for all 3 ng-model of the options dropdown. I changed it to be a 2 dimensional array, and just update the relevant one. I also changed the function to use the $index from the ng-repeat so the function will know what needs to be changed:
ng-change="loadPlanTemplates({{$index}})
and
$scope.loadPlanTemplates = function (index) { ... }
The array is initialized at the beginning:
$scope.plan_options = [[],[],[]];
And then in each case you have:
$scope.plan_options[index] = [
{plan_option_id: 1, name: '10 Years'},
{plan_option_id: 2, name: '20 Years'},
{plan_option_id: 3, name: '30 Years'},
];
break;
Plunker

ng-options for select box binding to hash

I'm a little confused on how to do a binding with AngularJS. I'm putting a <select> element in with an ng-model="variable.type". I've also got a $scope.type variable with is a hash table. The key of that hashtable is the variable.type.
So basically I want the select box to list all of the values from $scope.type, and then do the binding so that the variable.type is linked to the key of the hashtable. I'm just not sure how to specify the ng-options to do that.
<tr ng-repeat="variable in variables">
<td>
<select ng-model="variable.type" ng-options="????">
</select>
</td>
</tr>
If I'm understanding your question, you're basically asking how to use an object as a data source for ng-options. If $scope.type looks like this:
$scope.type = {
"type1": { value: "value1" },
"type2": { value: "value2" },
"type3": { value: "value3" }
};
And $scope.variables looks like this:
$scope.variables = [
{
id: 1,
name: "item1",
type: "type1"
},
{
id: 2,
name: "item2",
type: "type2"
},
{
id: 3,
name: "item3",
type: "type3"
}
];
Then you could bind it up like this:
<tr ng-repeat="variable in variables">
<td>
<select ng-model="variable.type" ng-options="key as vartype.value for (key, vartype) in type"></select>
</td>
</tr>
Demo

Resources