I try to sort data with angular.
Here my code:
<table id="data-table" width="100%" class="table table-striped table-hover">
<thead>
<tr>
<th class="sortable" field="name">Name</th>
<th class="sortable" field="phone">Phone number</th>
</tr>
</thead>
<tbody>
<tr class="tr-data" ng-repeat="el in list | orderBy:sortCol:sortType" >
<td>{{el.name}}</td>
<td>{{el.phone}}</td>
</tr>
</tbody>
</table>
<div>{{sortType}}</div>
<div>{{sortCol}}</div>
javascript:
var someData = [
{'name': 'Vasja', 'phone': '00375 29 654 1185'},
{'name': 'Sasha', 'phone': '00375 29 654 1176'}];
app.controller('myCtrl', function($scope)
{
$scope.sortType = false;
$scope.sortCol = 'phone';
$scope.list = someData;
$scope.applySort = function()
{
$('th.sortable').each(function(idx, el)
{
var uarr = $('<span class="sort-span" ng-click="xSort(this);">↑</span>');
var darr = $('<span class="sort-span">↓</span>');
uarr.appendTo(el).on('click', function() { $scope.sortCol = $(el).attr('field'); $scope.sortType = false;});
darr.appendTo(el).on('click', function() { $scope.sortCol = $(el).attr('field'); $scope.sortType = true;});
});
};
$scope.applySort();
});
By clicking on arrow - nothing changed. Even data sortCol and SortType don't changed.
But, when i change data in list - sorting is applying;
Angular couldn't fire it's events by jquery events. Either you could add $scope.$apply() to the end of your jquery events, it would work but this isn't a good solution.
The better way is to render your arrows in angular and bind events with angular.
Don't use jQuery, it should be done with Angular directives like ngClick:
<thead>
<tr>
<th class="sortable" field="name">
Name
<span class="sort-span" ng-click="sort('name', false)">↑</span>
<span class="sort-span" ng-click="sort('name', true)">↓</span>
</th>
<th class="sortable" field="phone">
Phone number
<span class="sort-span" ng-click="sort('phone', false)">↑</span>
<span class="sort-span" ng-click="sort('phone', true)">↓</span>
</th>
</tr>
</thead>
and controller:
app.controller('myCtrl', function ($scope) {
$scope.sortType = false;
$scope.sortCol = 'phone';
$scope.list = someData;
$scope.sort = function (field, type) {
$scope.sortCol = field;
$scope.sortType = type;
};
});
Related
In this plunk I have a table with ng-repeat, where one of the elements in the table is a directive. Problem is that directive field is not showing in the table. What's wrong with this code?
HTML
<table border="1">
<tr ng-repeat="row in rows">
<td>
{{row.x}}
</td>
<td>
<div some-directive field="row.field"></div>
</td>
</tr>
</table>
Javascript
var app = angular.module('app', []);
app.controller('myCtl', function($scope) {
$scope.rows = [{x: 1}, {x:2}];
});
app.directive('someDirective', function () {
var directive = {};
directive.restrict = 'EA';
directive.scope = {
field: '='
};
directive.link = function (scope, element, attrs) {
scope.field = "aaa";
};
return directive;
});
The answer is to add directive.template = "{{field}}";
I am receiving below data from my json object,
var dataFromServer='[
{
"Id":1,
"Name":"Province A",
"AreaDTO":[],
"SubStationDTO":[]
},
{
"Id":2,
"Name":"Province B",
"AreaDTO":[
{
"Id":1,
"Name":"ProvinceB Area A",
"ProvinceId":2,
"SubStationDTO":null
},
{
"Id":2,
"Name":"Province B Area B",
"ProvinceId":2,
"SubStationDTO":null
}],
"SubStationDTO":[
{
"Id":1,
"Name":" Province B Area A SubStation A",
"AreaId":1,
"MetersDTO":null
}
]
}
]';
Please see : http://jsfiddle.net/Jayaruvan/s8403t71/1/
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th>Province Name</th>
<th class="numeric">Area Count</th>
<th class="numeric">SubStation Count</th>
<th colspan="2"></th>
</tr>
</thead>
<tbody data-bind="foreach: ProvincesArray">
<tr>
<td><p data-bind="text: Name"></p></td>
<td ><p data-bind="text: Areas().length" ></p></td>
<td> <p data-bind="text: SubStations().length" ></p></td>
<td class=""><a class="btn-link" data-bind="click: $parent.EditProvince">Edit</a></td>
<td class=""><a class="btn-link" data-bind="click: $parent.RemoveProvince">Delete</a></td>
</tr>
</tbody>
</table>
I want it to bind above table and it's not working. Can anyone help?
I am referring this : http://jsfiddle.net/rVPBz/2/ as an example,
(Thank you ace for the proper formatting)
I have make a new Jsfiddle for your. I have fix some basic errors.
The table is implemented.
Your view model implementation was bad, I reorganised it.
var ProvinceViewModel = function () {
var self = this;
this.Province = function(data){
data = data || {};
this.Id = data.Id;
this.Name=data.Name;
this.Areas = ko.observableArray([]);
this.SubStations = ko.observableArray([]);
};
this.ProvincesArray = ko.observableArray([new this.Province()]);
this.Area = function(data){
data = data || {};
this.Id = ko.observable(data.Id);
this.Name = ko.observable(data.Name);
this.SubStations = ko.observableArray([]);
};
this.SubStation = function(data){
data = data || {};
this.Id = ko.observable(data.Id);
this.Name = ko.observable(data.Name);
this.Meters = ko.observableArray([]);
};
this.ProvincesArray = ko.utils.arrayMap(dataFromServer, function(item) {
var Province = new self.Province(item);
var Area= new self.Area(item);
var SubStations= new self.SubStation();
return Province;
});
};
ko.applyBindings(new ProvinceViewModel());
You can see the new structure which work, you can add any paramet
http://jsfiddle.net/YvanBarbaria/s8403t71/15/
My problem is that when I click a row that is data-bound in KnockoutJS, the data that is sent to my selectItem function is empty and only displays {"data":{}} in the Firefox Web Console.
What I do not understand is how to get the values of my table cells so that I can refer to the sender portion of my JSON object? At the moment, it is empty.
KnockoutJS:
function ServiceViewModel() {
var self = this;
self.rows = ko.observableArray();
$.ajax({
method: "GET",
url: "URL",
success: function(data) {
var observableData = ko.mapping.fromJSON(data);
var array = observableData();
self.rows(array);
}
});
self.computedRows = ko.computed(function() {
if(!self.query()) {
return self.rows();
} else {
return ko.utils.arrayFilter(self.rows(), function(row) {
return row.sender() == self.query();
});
}
});
self.selectedItem = ko.observable();
self.selectItem = function(data) {
self.selectedItem(data);
console.log(JSON.stringify(self.selectedItem()));
};
};
$(document).ready(function() {
var svc = new ServiceViewModel();
ko.applyBindings(svc);
});
JSON:
[{"statusmsg":"OK","data":{"status":"running"},"sender":"hostname","statuscode":0}]
HTML:
<div class="table-responsive">
<table class="table table-condensed table-striped table-bordered table-hover">
<thead>
<tr>
<th>Host</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody data-bind="foreach: computedRows().sort(function(l, r) { return l.sender() > r.sender() ? 1 : -1})">
<tr data-bind="click: $root.selectItem">
<td data-bind="text: sender"></td>
<td><span data-bind="text: data.status"></span></td>
<td>
<div class="btn-group">
<button data-bind="click: $root.selectItem">Start</button>
<button>Stop</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
You need to use ko.toJSON to convert your knockout model to json instead of JSON.stringify as knockout uses functions for the observables.
console.log(ko.toJSON(self.selectedItem()));
I have a simple sample data like this
var data = {
"Lines": [
{"Entries": [{"Hours": 5.5},{"Hours": 2.50},{"Hours": 3.75}]},
{"Entries": [{"Hours": 5.1},{"Hours": 2.00},{"Hours": 4.75}]},
{"Entries": [{"Hours": 1.2},{"Hours": 3.00},{"Hours": 2.12}]
}]
}
Here is my model
function ViewModel() {
var self = this
self.List = ko.observableArray([])
self.LoadData = function () {
var data = {
"Lines": [
{"Entries": [{"Hours": 5.5},{"Hours": 2.50},{"Hours": 3.75}]},
{"Entries": [{"Hours": 5.1},{"Hours": 2.00},{"Hours": 4.75}]},
{"Entries": [{"Hours": 1.2},{"Hours": 3.00},{"Hours": 2.12}]
}]
}
self.List(ko.mappings.fromJS(data.Lines))
////this makes every child observable
}
self.LoadData()
}
$('document').ready(function () {
ko.applyBindings(new ViewModel())
})
Here is my view
<table id="myTable" class="tablesorter">
<thead>
<tr>
<th>Mon 1 </th>
<th>Mon 2 </th>
<th>Mon 3 </th>
</tr>
</thead>
<tbody data-bind='foreach:Lines'>
<tr data-bind='foreach:$data.Entries'>
<td>
<input type="text" data-bind="value:Hours"/>
</td>
</tr>
</tbody>
</table>
Here is sample view
here is the output i want
You can see i am adding a column and a row which need to add and these should be observables. how can i do it. I have no idea where to start from.
You just need to add a computedObservable to each row (updated fiddle: http://jsfiddle.net/kL79d/4/) :
html:
<table id="myTable" class="tablesorter">
<thead>
<tr>
<th>Mon 1 </th>
<th>Mon 2 </th>
<th>Mon 3 </th>
<th>Total </th>
</tr>
</thead>
<tbody data-bind='foreach:List'>
<tr>
<!-- ko foreach:Entries-->
<td>
<input type="text" data-bind="value:Hours, valueUpdate:'afterkeydown'"/>
</td>
<!-- /ko -->
<td>
<span data-bind="text:Total"></span>
</td>
</tr>
</tbody>
</table>
js:
function ViewModel() {
var self = this
self.List = ko.observableArray([])
self.LoadData = function () {
var data = {
"Lines": [
{"Entries": [{"Hours": 5.5},{"Hours": 2.50},{"Hours": 3.75}]},
{"Entries": [{"Hours": 5.1},{"Hours": 2.00},{"Hours": 4.75}]},
{"Entries": [{"Hours": 1.2},{"Hours": 3.00},{"Hours": 2.12}]
}]
}
self.List(ko.mapping.fromJS(data.Lines)())
////this makes every child observable
}
self.applyTotals = function(){
ko.utils.arrayForEach(self.List(), function(vm){
vm.Total = ko.computed(function(){
var s = 0;
ko.utils.arrayForEach(this.Entries(), function(entry){
var p = parseFloat(entry.Hours(), 10);
if (!isNaN(p)) {
s += p;
}
});
return s;
}, vm);
});
}
self.LoadData();
console.log(self.List());
self.applyTotals();
}
ko.applyBindings(new ViewModel())
To get the column totals, do the same thing on the vertical. For easier access to the data values, you might want to keep the data in data structure which allows easy iteration for both rows and columns.
In the documentation for the mapping plugin, there's a section called "Customizing object construction using 'create'". This shows how you can control the mapping of the json data to an observable object -- including augmenting the object with additional functionality (like the computedObservable #pax162 mentioned).
It's basically the same approach #pax162 mentioned, but in a more automated fashion.
In this example:
function onRowClickHandler(evt){
var clickedTaxLotId = grid.getItem(evt.rowIndex).PARCELID;
var selectedTaxLot;
dojo.forEach(map.graphics.graphics,function(graphic){
if((graphic.attributes) && graphic.attributes.PARCELID === clickedTaxLotId){
selectedTaxLot = graphic;
return;
}
});
var taxLotExtent = selectedTaxLot.geometry.getExtent();
map.setExtent(taxLotExtent);
}
And they select the PARCELID from here:
<th field="PARCELID">Parcel ID</th>
<th field="OWNERNME1" >Owner 1</th>
<th field="OWNERNME2">Owner 2</th>
<th field="RESYRBLT ">Year Built</th>
<th field="SITEADDRESS" width="100%">Address</th>
But now my problem is that i have a <th field="1"> that isnt changeable. But i need to get that value like this var clickedTaxLotId = grid.getItem(evt.rowIndex).2; but in javascript that isnt possible.
table header looks like this:
<div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'bottom'" style="height:350px;" >
<table data-dojo-type="dojox.grid.DataGrid" jsid="grid" id="grid" data-dojo-props="rowsPerPage:'5', rowSelector:'20px'">
<thead>
<tr>
<th field="0" width="auto" >
Gezocht op
</th>
<th field="1" width="auto" >
Gevonden
</th>
</tr>
</thead>
</table>
EDIT
Here i set the value of the th field. This gets done by dataForGrid. the first field is "0" and gets filled with result.foundFieldName, "1" with result.value
map.graphics.clear();
var dataForGrid = [];
//Build an array of attribute information and add each found graphic to the map
dojo.forEach(results, function(result) {
var graphic = result.feature;
dataForGrid.push([result.foundFieldName, result.value]);
var userlabel = result.value;
switch (graphic.geometry.type) {
case "point":
graphic.setSymbol(markerSymbol);
break;
case "polyline":
graphic.setSymbol(lineSymbol);
break;
case "polygon":
graphic.setSymbol(polygonSymbol);
break;
}
map.graphics.add(graphic);
});
var data = {
items: dataForGrid
};
var store = new dojo.data.ItemFileReadStore({
data: data
});
grid.setStore(store);
}