My FIXTURES contains array of products which i want to sort based on ID.
Astcart.Application.FIXTURES=[
{
"name" : "astr",
"home_products": [
{
"id": 3,
"name": "Mobiles & Accessories"
},
{
"id": 2,
"name": "Mobiles & Accessories"
},
{
"id": 1,
"name": "Mobiles & Accessories"
}
]
}
];
I am not getting complete example of EMBER.SORTABLEMIXIN.I don't have any idea about sorting in ember.
Can anyone explain me how to do sorting in ember using my this example(Not working)?
The sortable feature is provided by Ember.SortableMixin. This mixin expose two properties: sortAscending and sortProperties.
The sortAscending accepts a boolean value determining if the sort is ascendant or not.
And the sortProperties expect an array with the properties to sort.
For instance:
Controller
App.IndexController = Ember.Controller.extend(Ember.SortableMixin, {
sortAscending: false,
sortProperties: ['id'],
});
These properties can be changed and the order will be updated, here is a sample with dynamic sort:
Controller
App.IndexController = Ember.Controller.extend(Ember.SortableMixin, {
sortProperties: ['firstName'], // or whatever property you want to initially sort the data by
sortAscending: false, // defaults to "true"
actions: {
sortBy: function(property) {
this.set('sortProperties', [property]);
}
}
});
To access the arranged content, you should refer to arrangedContent in your template instead of the regular model property. Like this:
Template
<script type="text/x-handlebars" data-template-name="index">
<h2>Index Content:</h2>
<table>
<thead>
<th {{action "sortBy" "id"}}>ID</th>
<th {{action "sortBy" "firstName"}}>First Name</th>
<th {{action "sortBy" "lastName"}}>Last Name</th>
</thead>
<tbody>
{{#each arrangedContent as |prop|}}
<tr>
<td>{{prop.id}}</td>
<td>{{prop.firstName}}</td>
<td>{{prop.lastName}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
You can see this working here http://emberjs.jsbin.com/gunagoceyu/1/edit?html,js,output
I hope it helps
Since Ember.SortableMixin is going to be deprecated in Ember 2.0 (as well as the ArrayController), the recommended way to sort will be using Ember.computed.sort(), as illustrated here: https://stackoverflow.com/a/31614050/525338
Related
I get a nested JSON object back from an API call that looks something along the lines of this:
{
"name": “Main “Folder”,
"children": [
{
"name": “Child Folder 1”,
"children": []
},
{
"name": “Child Folder 2”,
"children": [
{
"name": “Sub Folder 1”,
"children": [
{
“name”: “Sub Sub Folder 1”,
“children”: []
}
]
},
{
"name": “Sub Folder 2” ,
"children": []
}
]
}
]
}
There is no limit on how far the JSON object can be nested so that is unknown to me. I need to have all of the children of the folders to be indented under the parent in the table. I'm not really even sure how to go about doing this. The first thing I tried was doing something like this in my HTML file, but I quickly realized it wasn't going to work.
folders.html
<table>
<thead>
<tr><strong>{{ this.tableData.name }}</strong></tr>
</thead>
<tbody ng-repeat="b in this.tableData.children">
<tr>
<td>{{ b.name }}</td>
<td ng-repeat="c in b.children">{{ c.name }}</td>
</tr>
</tbody>
</table>
folders.js
export default class FoldersController {
constructor($rootScope, $scope, $uibModal) {
this.tableData = {Example Data from top}
}
}
Is there a not too complicated way to go about doing this? Thanks!
You should create a component with a template that contains a table, then you can nest your component inside itself to follow the tree structure logical path:
Your root controller should contain your table data:
angular.module('app').controller('RootCtrl', ['$scope', function($scope) {
// assigning the data to $scope to make it available in the view
$scope.tableData = {Example Data from top};
}]);
Your tree component could be something on this lines:
angular.module('app').component('treeComponent', {
controller: 'TreeCtrl',
bindings: {
tree: '<',
},
templateUrl: 'tree-view.html'
});
your root template should load the first instance of the component:
<div>
<tree-component tree="tableData"></tree-component>
</div>
then the component template should take care of the the recursion when required;
tree-view.html:
<table class="record-table">
<thead>
<tr>
<th>
<strong>{{ $ctrl.tableData.name }}</strong>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="node in $ctrl.tableData.children">
<td>{{node.name}}</td>
<td ng-if="node.children.length > 0">
<tree-component tree="node.children"></tree-component>
</td>
</tr>
</tbody>
</table>
creating indentation then becomes easy using basic css:
.record-table .record-table {
padding-left: 20px
}
I was able to figure out a solution of my own using recursion in the js file. I implemented mindthefrequency's answer as well and it seems to be working just fine. I'm marking it as the best answer because it seems to be the cleaner solution, but I'm posting what I have in case someone wants to take a more js oriented approach.
First, in the js file, use recursion to add all of the nodes and how far each needs to be indented to the table data variable.
folders.js
export default class FoldersController {
constructor($rootScope, $scope, $uibModal) {
this.resp = {Example Data from top}
this.tableData = []
this.createTable(this.resp.children, 0, [
{
name: this.resp.name,
indent: '0px',
},
]);
}
createTable(children, count, data) {
count += 1;
// base case
if (!children || children.length === 0) {
return;
}
for (const child of children) {
const { name } = child;
const returnData = data;
returnData.push({
name: name,
indent: `${count * 25}px`,
});
this.tableData = returnData;
this.createTable(child.children, count, returnData);
}
}
}
Then, in the html file, use angularjs to properly indent each node
folders.html
<table>
<thead>
<tr><strong>Table Header</strong></tr>
</thead>
<tbody ng-repeat="b in vm.tableData">
<tr>
<td ng-style="{'padding-left': b.indent}">{{ b.name }}</td>
</tr>
</tbody>
</table>
Trying to get my ajax to load into data tables. I want to load 2 tables from the same ajax call but I can't even get 1 to load first. Let's get some snippet action going...
$(function() {
$("#tablepress-1").DataTable({
ajax: {
url: '/api/?action=getStats',
dataSrc: 'data',
"deferRender": true
},
"columns": [{
"instances": "Strategy"
},
{
"instances": "Exchange"
},
{
"instances": "Trades"
},
{
"instances": "PL"
},
{
"instances": "Uptime"
}
]
})
})
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<table id="tablepress-1" class="tablepress tablepress-id-1">
<caption style="caption-side:bottom;text-align:left;border:none;background:none;margin:0;padding:0;">Edit</caption>
<tbody>
<tr class="row-1">
<td class="column-1">Strategy</td>
<td class="column-2">Exchange</td>
<td class="column-3">Trades</td>
<td class="column-4">PL</td>
<td class="column-5">Uptime</td>
</tr>
</tbody>
</table>
Since stack snippets don't support ajax data, I'll paste it here:
{"success":true,"data":{"instances":[{"Strategy":"...","Exchange":"...","Trades":"...","PL":"...","Uptime":"..."}],"trades":[{"Open":"...","Strategy":"...","Exchange":"...","Direction":"...","Size":"...","PL":"...","Close":"...","ID":"..."}]},"meta":{"botOnline":true,"threadCount":0,"balance":0.0028}}
Right now I just have my script outputting ... for each field. What happens is that the table headings disappear and no data ever gets loaded into the table.
I tried setting up a fiddle with the data source but it's my first time trying to use the echo feature. Maybe someone else knows how to do that: https://jsfiddle.net/Trioxin/kjhtn7wm/6/
I can't imagine what's wrong here. I thought I specified the json format properly but it appears not.
Regarding cross domain AJAX sources in jsfiddles you can use http://myjson.com
Your "table headings" disappear because they are not table headings. They are just a <tbody> row that will be removed as soon DataTables get some data. Do this instead:
<thead>
<tr class="row-1">
<th class="column-1">Strategy</th>
<th class="column-2">Exchange</th>
<th class="column-3">Trades</th>
<th class="column-4">PL</th>
<th class="column-5">Uptime</th>
</tr>
</thead>
You must either pass an array of objects or point to the path of that array, like dataSrc: data.instances. You could also have dataSrc: function(data) { return data.data.instances }
You define which object property that should be mapped into which column through the data option like { data: "Strategy" }:
columns: [
{ data: "Strategy" },
{ data: "Exchange" },
{ data: "Trades" },
{ data: "PL" },
{ data: "Uptime" }
]
forked fiddle -> https://jsfiddle.net/hfc10sxt/
I have an object with a couple dozens of settings, some settings depend on other settings, so, I need to observe if some setting changed.
import Ember from 'ember';
export default Ember.Controller.extend({
allPermissionChanged: function () {
alert('!');
}.observes('hash.types.[].permissions'),
permissionsHash: {
orders:{
types: [
{
label: 'All',
permissions: {
view: true,
edit: false,
assign: false,
"delete": false,
create: true
}
},
}
],
permissions:[
{
label:'Просмотр',
code:'view'
},
{
label:'Редактирование',
code:'edit'
},
{
label:'Распределение',
code:'assign'
},
{
label:'Удаление',
code:'delete'
},
{
label:'Создание',
code:'create'
}
]
}
}
});
Next I try to bind each setting to input
<table class="table table-bordered">
<thead>
<tr>
{{#each hash.types as |type|}}
<th colspan="2">{{type.label}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each hash.permissions as |perm|}}
<tr>
{{#each hash.types as |type|}}
{{#if (eq (mut (get type.permissions perm.code)) null)}}
<td> </td>
<td> </td>
{{else}}
<td>{{perm.label}}</td>
<td>{{input type="checkbox" checked=(mut (get type.permissions perm.code)) }}</td>
{{/if}}
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
But observer doesn't work.
Also I prepared Jsbin example - http://emberjs.jsbin.com/havaji/1/edit?html,js,output
You are using the wrong syntax for that. hash.types.[] should only be used if you want to observe an actual array, when something is added or removed from it. To observe a property in an array you you hash.types.#each.permissions.
allPermissionChanged: function () {
alert('!');
}.observes('hash.types.#each.permissions')
You can read more about it in the Ember Guides.
You could change booleans to objects with boolean property so you could properly observe value of checkbox.
Controller:
App.IndexController = Ember.Controller.extend({
testData: Ember.ArrayProxy.create({
content: [
{ value: true },
{ value: false },
{ value: true }
]
}),
//...
Template:
{{input type='checkbox' checked=data.value}}
Observer:
arrayChanged: Ember.observer('testData.#each.value', function () {
console.log('changed');
})
Working demo.
I have read the ember guide to achieve the same in my Ember Application, but i can't.
I am trying to configure my view with a Controller which makes a multiplication between two values
Here the code:
App.TotalView = Ember.View.extend({
attributeBindings: ['value', 'placeholder'],
placeholder: null,
value: '',
total: (function() {
return this.get('newThread.selectContentTariffa') * this.get('newThread.primary');
}).property('newThread.selectContentTariffa', 'newThread.primary')
});
Here in the view:
<td>{{view "total" valueBinding=newThread.value}}</td>
I can not get the result of this multiplication in this view,is this code correct? what's wrong?
You can see here: http://emberjs.jsbin.com/qakado/edit
By only focusing on the issue you are facing and not the design and based on the code you have provided, there are the following issues and corresponding possible solutions applied to the examples at the end,
there are calls to newThread but it is not defined anywhere - create a newThread in controller
the view helper uses total you may either create a template and associate it with App.TotalView or use the block form of view helper - 1st example uses a template, 2nd uses block form
js
App.ThreadsController=Ember.ArrayController.extend({
selectContentTariffa: [
{label: "180", value: "180"},
{label: "200", value: "200"},
{label: "300", value: "300"}
],
newThread:{
value:null,
selectContentTariffa:null,
primary:null
}
});
App.TotalView = Ember.View.extend({
templateName:"total",
attributeBindings: ['value', 'placeholder'],
placeholder: null,
value: '',
total: (function() {
var res= parseInt(this.get('controller.newThread.selectContentTariffa')) * parseInt(this.get('controller.newThread.primary'));
return isNaN(res)?"":res;
}).property('controller.newThread.selectContentTariffa', 'controller.newThread.primary')
});
hbs - example1
<script type="text/x-handlebars" data-template-name="threads">
<table class="table table-bordered table-hover">
<tr><th>Title 1</th><th>Title 2</th><th>Title 3</th></tr>
<tr>
<td>{{view Ember.Select prompt="Tariffa" valueBinding=newThread.selectContentTariffa content=selectContentTariffa optionValuePath="content.value" optionLabelPath="content.label"}}</td>
<td>{{view Em.TextField type="number" valueBinding=newThread.primary class="form-control"}}</td>
<td>{{view "total"}}</td>
</tr>
</table>
</script>
<script type="text/x-handlebars" data-template-name="total">
this is total:{{view.total}}
</script>
hbs-example2
<script type="text/x-handlebars" data-template-name="threads">
<table class="table table-bordered table-hover">
<tr><th>Title 1</th><th>Title 2</th><th>Title 3</th></tr>
<tr>
<td>{{view Ember.Select prompt="Tariffa" valueBinding=newThread.selectContentTariffa content=selectContentTariffa optionValuePath="content.value" optionLabelPath="content.label"}}</td>
<td>{{view Em.TextField type="number" valueBinding=newThread.primary class="form-control"}}</td>
<td>{{#view "App.TotalView"}}t:{{view.total}}{{/view}}</td>
</tr>
</table>
</script>
example1 - http://emberjs.jsbin.com/falafezijo/edit?html,js
example2 - http://emberjs.jsbin.com/cuxafigiqe/1/edit?html,js
Is the following possible and if so how do I change my HTML to allow it?
I have the following model;
prospect = [{"name":"jamie",
"phones": [{
"type":"home",
"number":"01275"},
{
"type":"mobile",
"number":"0788"}]},
{"name":"peter",
"phones": [{
"type":"mobile",
"number":"07852"}]}
]
and I would like to display - in an angularjs table - like this
name home mobile
jamie 01275 0788
peter 07852
My current HTML
<table>
<tbody ng-repeat='person in prospect'>
<th>Name</th>
<th ng-repeat="phone in person.phones">{{phone.type}}</th>
<tr>
<td>
{{person.name}}
</td>
<td ng-repeat='phone in person.phones'>
{{phone.number}}
</td>
</tr>
</tbody>
</table>
produces
Name home mobile
jamie 01275 0788
Name mobile
peter 07852
http://jsfiddle.net/jaydubyasee/D7f2k/
To do this in html, without modifying your json, I'd first add an array that indicates what type of phone goes into each column:
$scope.types= ["home","mobile"];
Then use it in the header:
<th ng-repeat="type in types">{{type}}</th>
Then to print out the phone numbers we iterate over each phone within each column, using ngIf to conditionally show any phones that match that column's type:
<td ng-repeat='type in types'>
<span ng-repeat='pphone in person.phones' ng-if="pphone.type == type">
{{pphone.number}}
</span>
</td>
updated fiddle
A variation would be to replace the nested ngRepeats with a custom directive that displays the correct phone for the given column and row.
I hope you will like this solution :)
I did you this dependency
bower install angular
bower install ng-tasty
bower install bootstrap
And here the full solution
<div tasty-table bind-resource="resource">
<table class="table table-striped table-condensed">
<thead tasty-thead></thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-bind="row.name"></td>
<td ng-bind="row.phones | filterTypeColumn:'home'"></td>
<td ng-bind="row.phones | filterTypeColumn:'mobile'"></td>
</tr>
</tbody>
</table>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/ng-tasty/ng-tasty-tpls.min.js"></script>
<script>
angular.module('stackOverflowAnswer', ['ngTasty'])
.filter('filterTypeColumn', function() {
return function (input, typeColumn) {
var phoneNumber;
input.forEach(function (phone) {
if (phone.type === typeColumn) {
phoneNumber = phone.number;
}
})
return phoneNumber;
};
})
.controller('StackOverflowController', function ($scope) {
$scope.resource = {
"header": [
{ "name": "Name" },
{ "home": "Home" },
{ "mobile": "Mobile" }
],
"rows": [
{
"name":"jamie",
"phones": [
{ "type":"home","number":"01275" },
{ "type":"mobile", "number":"0788"}
]
},
{
"name":"peter",
"phones": [
{ "type":"mobile","number":"07852"}
]
}
]
};
});
</script>
</body>
</html>
If you want know more about ngTasty you can find all the doc here http://zizzamia.com/ng-tasty/directive/table .
For your specific case, the solution was make a custom filter.
Ciao