What is best way to do column totals in ng-grid? - ng-grid

If I have columns (name, amount) how do I best create a row / footer that shows ("Total",8877)? Clearly you can do it by adding a row to the data, but this ruins the sorting capability. It appears relatively easy to group by name and show the amount for each name, but I have not found how to do the simpler case (though I have found others asking - https://github.com/angular-ui/ng-grid/issues/679 for example)

You can include a custom footer template on the gridOptions. I looked for the default formatting of the footer in the source code and copied that, but added the function that calculates the totals. Something like this:
$scope.gridOptions = {
data: 'hereGoesTheData',
columnDefs : [list of your column names],
showFooter: true,
footerTemplate:
'<div ng-show="showFooter" class="ngFooterPanel" ng-class="{\'ui-widget-content\': jqueryUITheme, \'ui-corner-bottom\': jqueryUITheme}" ' +
'ng-style="footerStyle()"><div ng-style="{ \'cursor\': row.cursor }" ng-repeat="col in renderedColumns" ng-class="col.colIndex()" class="ngCell {{col.cellClass}} " ng-cell style="text-align:right;">' +
'{{getTotal(col.field)}}</div></div>'
};
And then define $scope.getTotal to do whatever you want it to do.

Quite possibly not the best solution, but I ended up adding a totals row to the top of the footer. https://github.com/mchapman/forms-angular/commit/9f02ba1cdafe050f5cb5e7bb7d26325b08c85ad2

without modifying ng grid, you could just provide your own footer template, that somehow gets the total for each column.
In my case, as I ""build"" the table from server data, I also accumulate a totals hash.
My template looks like this:
total_cell_footer = """
<div ng-show="showFooter" class="ngFooterPanel" ng-class="{'ui-widget-content': jqueryUITheme, 'ui-corner-bottom': jqueryUITheme}" ng-style="footerStyle()">
<div class="ngTotalSelectContainer" >
<div ng-style="{ 'cursor': row.cursor }" ng-repeat="col in renderedColumns" ng-class="col.colIndex()" class="ngCell {{col.cellClass}}">
<span class="ngCellText">{{ get_total(col) | currency:"$"}} </span>
<div class="ngVerticalBar" ng-style="{height: rowHeight}" ng-class="{ ngVerticalBarVisible: !$last }"> </div>
</div>
</div>
</div>
"""
The get_total function is defined in my scope (which is the parent of the ngGrid scope, hence inherited), as follows:
$scope.get_total= (col) ->
# used by the footer template to access column totals.
$scope.totals[col.field]

Take a look at the "Server side paging" example it has exactly what you want! you can slice and dice depending on what you need.
http://angular-ui.github.io/ng-grid/
in your grid options put
enablePaging: true,
showFooter: true,
showFilter: true,
totalServerItems: 'totalServerItems',
pagingOptions: $scope.pagingOptions,
and up top
$scope.pagingOptions = {
pageSizes: [100, 500, 1000],
pageSize: 100,
totalServerItems: 0,
currentPage: 1
};
$scope.setPagingData = function (data, page, pageSize) {
var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
$scope.myData = pagedData;
**$scope.pagingOptions.totalServerItems = data.length**;
if (!$scope.$$phase) {
$scope.$apply();
}
};

Related

paper-dropdown-menu's label not updating when menu items are added dynamically

When paper-dropdown-menu items are dynamically added its label will not update,
but its selected value is changing ,which is not displaying in label
It's illustrated in PLUNKER : https://plnkr.co/edit/jy7WxttkB1mN7z0uHuVJ?p=preview
<paper-dropdown-menu label="Patient">
<paper-menu class="dropdown-content" selected="{{selectedPatient}}" attr-for-selected="value">
<template is="dom-repeat" id="patientMenu" items="[[patientsList]]">
<paper-item class="patient-names" value="[[item.id]]">[[item.id]][[item.name]]</paper-item>
</template>
</paper-menu>
<paper-button on-tap="_fun" raised>change Array list</paper-button>
<div style="color:blue;">selected patient id--->[[selectedPatient]]</div>
Polymer({
is: 'my-test',
properties: {
patientsList:{
type:Array
}
},
ready:function() {
this.patientsList =[
{id:0,name:"aaa"},
{id:1,name:"bbb"},
{id:2,name:"ccc"},
{id:3,name:"ddd"},
{id:4,name:"eee"}
];
this.selectedPatient = 0;
},
_fun:function(){
this.selectedPatient = null;
this.patientsList = [
{id:100,name:"xxx"},
{id:101,name:"yyy"},
{id:102,name:"qqq"},
{id:103,name:"mmm"},
{id:4,name:"eee"}
];
this.selectedPatient = 100;
}
I trying your plunker, especially the "it work the second time" part, make think that the issue can be that the dom-repeat hadn't time to updates the items when the
this.selectedPatient = 100;
is executed.
I tried to change it to a
this.async(function(){
this.set('selectedPatient',100)
}.bind(this));
to make sure the selectedPatient is set only after the dom-repeat is updated, and it seems to do the trick.

using foundation 5 joyride with tabs

Is there a way to switch tabs with foundation 5 Joyride?
I have foundation tabs on the page and want Joyride to point elements on different tabs.
Like mentioned in the comment from Steven, you could use the callback either in the pre or post step callback function you activate the tab you need.
post_step_callback : function (){}, // A method to call after each step
pre_step_callback : function (){} // A method to call before each step
Hope this helps...
Here's what worked for me. I looked around and couldn't find anything useful, so wrote this. The hardest part was figuring out how to get the id of the target anchor. This was found buried in the 'this' object available to the callback.
$(this.$target)[0].id;
The 'content' class is used by foundation to identify the content to display when a tab is clicked. So traversing up the .parents tree finding the enclosing elements gives you the content tab(s) holding your link. And then of course you have to add an id to the <a> element of the tab you want to click. If you name it the same as your content div, with '-a' appended, you should be good to go.
html:
<dl class="tabs radius" data-tab id="my_tabs">
<dd class="active">Tab 1</dd>
<dd class="active">Tab 2</dd>
</dl>
<div class="tabs-content">
<div class="content" id="tab1">
<article id="joyride_stop1">...</article>
</div>
<div class="content" id="tab2">
<article id="joyride_stop2">...</article>
</div>
</div>
js:
$(document).ready(function() {
$(document).foundation('joyride', 'start', {
pre_step_callback: function(i, tip) {
var target = $(this.$target)[0].id;
if($('#' + target).parents('.content').length > 0) {
$('#' + target).parents('.content').each(function() {
var id = $(this).attr('id');
if($('#' + id).is(':visible') == false) {
$('#' + id + '-a').click();
}
});
}
}
});
});
This will work on any page, whether it contains tabs or not, so it can be universally included across a site.

List with ajax-loading details in AngularJS

For a list of items I want to show details after item click. Details will be loaded with ajax request.
I have something similar to this: http://jsfiddle.net/asmKj/
How to modify this to work with details loaded dynamically?
For sure I have to prepare function in my controller like this:
$scope.getDetails = function (name) {
return $scope.details = myService.getDetails(name).then(function (details) {
return $scope.details = details;
});
}
But how to bind this data to details div?
I would rather change with something like this:
HTML
<ul class="procedures" ng-app ng-controller="sample">
<li ng-repeat="procedure in procedures">
<h4>{{procedure.definition}}</h4>
<div class="procedure-details" ng-show="procedures.isVisible">
<p>Number of patient discharges: {{procedure.discharged}}</p>
</div>
</li>
</ul>
JS
$scope.procedures = [
{
definition: 'Procedure 1',
discharged: 23
},
{
definition: 'Procedure 2',
discharged: 2
},
{
definition: 'Procedure 3',
discharged: 356
}
];
$scope.getDetails = function ($index) {
$http.get('your-url').success(
// use the data retrieved
procedures[$index].isVisible = !procedures[$index].isVisible;
);
}
There are basically two options.
Put everything in your procedure objects as separate properties (when the details are loaded) -- then you can just use procedure.showDetails in ng-repeat.
Use $index to get index from your procedures -- then you can use it to access any arbitrary collection from your scope in ng-repeat.
(may update my answer, when you provide more info about structure of your data; and if still needed)

CodeIgniter & script.aculo.us InPlaceEdit produces duplicates on update

I'm working on a CI project and implemented scriptaculous InPlaceEdit. It works, but behaves strangly when and after updating a value.
1) When I click to edit, even though the field is just one word and should be 1 line, it produces a text area with 3 cols and 50 rows. It seems the script added empty space before the original value.
2) I save the new value and want to re-edit it, it gives me twice the form. after that 4x and so on...
HTML
So when the site is rendered, the line looks like this:
<h2 id="case_title-editme-27" class="editable savetitle" onclick="EditInput('case_title','27', 'cases');"> One line </h2>
Clicking to edit in place procudes:
<form id="case_title-editme-27-inplaceeditor" class="input-edit">
<textarea class="editor_field" rows="3" cols="40" name="value"></textarea>
<br>
<input class="editor_ok_button" type="submit" value="Save">
<a class="editor_cancel_link editor_cancel" href="#">cancel</a>
</form>
<h2 id="case_title-editme-27" class="editable savetitle" onclick="EditInput('case_title','27', 'cases');" title="Click to edit" style="display: none;"> One line </h2>
Here's my JS:
function EditInput(field, id, table) {
var id = id;
var table = table;
var field = field;
new Ajax.InPlaceEditor(
field+'-editme-'+id,
'<?PHP echo base_url();?>saveajax/'+id, {
okText: 'Save',
formClassName: 'input-edit',
callback: function(form, value) { return 'table=' + table + '&field=' + field + '&value=' + escape(value) },
}
);
}
And the PHP view
<?php foreach($caseheadlines as $headline):?>
<h2 class="editable savetitle" id="case_title-editme-<?php echo $headline['case_id']; ?>" onclick="EditInput('case_title','<?PHP echo $headline['case_id']; ?>', 'cases');">
<?php echo $headline['case_title']; ?>
</h2>
<?php endforeach;?>
So when clicking on the div, the js function get's fired and everything works expect the problems above. controller and models are fine, data get's saved to the DB.
Anyone has any idea?
The javascript you have provided is creating multiple inplace editors. I would change it like this.
for all the fields that you want to have editable add a specific class to those fields. I see you already have the editable class on the <h2> above - lets use that.
When the DOM is loaded trigger all those elements with that class to be inplace editors like this
document.observe("dom:loaded",function(){
$$('.editable').each(function(element){
new Ajax.InPlaceEditor(element,
'<?PHP echo base_url();?>saveajax/'+id, {
rows : 1,
cols : 15,
okText: 'Save',
formClassName: 'input-edit',
callback: function(form, value) { return 'table=' + table + '&field=' + field + '&value=' + escape(value) },
}
);
});
});
Now there will only be 1 instance of the inplace editor for each field. The inplace editor handles the on click turn into an editable field part.
as far as the row and cols problem if you set the rows and cols options in the instance for exactly what you want that should help - I've added them to my example

Rails 3 and Formtastic. How to display fields according to selection (ajax)?

If I have shipments, each shipment has one of four possible modes. When I want to create an invoice, I go to New Invoice, select shipment from select menu (what shipment the invoice is for). If the shipment selected has mode A, then some fields will be displayed in the form; If the shipment selected has mode B, then some other fields will be displayed.
All I need is that in the New Invoice form, when someone selected a shipment, to ajaxily find the shipment's mode (shipment.mode).
You can implement this in a way similar to this:
Your view:
<div data-shipment-mode="A" style="display:none;">
fields that should only be shown for shipment mode A
</div>
<div data-shipment-mode="B" style="display:none;">
fields that should only be shown for shipment mode B
</div>
Your JavaScript:
$(document).ready(function() {
$('id-of-shipment-select-menu').change(function() {
var successHandler = function(data) {
var mode = data.mode;
$("div[data-shipment-mode!=" + mode + "]").hide();
$("div[data-shipment-mode=" + mode + "]").show();
};
var shipmentId = $(this).val();
/* replace service_url with the appropriate controller/action */
$.getJSON("/service_url/" + shipmentId, successHandler);
});
});
Initially all mode-dependent fields are hidden. Then when you select a shipment, the change callback will be invoked. It sends a request to a service (controller action) that returns the mode for the given shipment. And you use this mode and only show those divs that their data-shipment-mode has the same value.
You can even expand this, and when you hide a div, you can clear the values of all the inputs (and selects, etc.) within it as well as disabling them.
You can avoid sending the request to the server, if you embed the mode for each shipment in its option tag:
View:
<option id="A_SHIPMENT_ID"
data-shipment-mode="SHIPMENT_MODE_FOR_THIS_SHIPMENT">
Shipment A
</option>
JavaScript:
$(document).ready(function() {
$('id-of-shipment-select-menu').change(function(e) {
var mode = $(e.target).data("shipment-mode");
$("div[data-shipment-mode!=" + mode + "]").hide();
$("div[data-shipment-mode=" + mode + "]").show();
});
});

Resources