paper-datatable
paper-datatable copied to clipboard
Formatting function not working
I have the following table column definition:
<paper-datatable-column header="amount" property="paymentAmount" format-value="{{cellCurrencyFormat}}" align="right"></paper-datatable-column>
The cellCurrencyFormat
function is in an external script file, containing helper functions that are used throughout the application.
cellCurrencyFormat = function (value) {
var cellFormat = formatCurrency (value, 'R', 2);
console.log(cellFormat);
return cellFormat;
};
This function is a wrapper around the main formatting function:
function formatCurrency (value, currency, precision) {
if (!value) {
return '';
};
if (isNaN(value)) {
return "Value is not a Number";
} else {
currency = currency || "$";
precision = precision || 2;
value = Number(value);
value = value.toFixed(precision);
}
var parts = value.split('.'),
fnum = parts[0],
decimal = parts[1] ? '.' + parts[1] : '';
return currency + fnum.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') + decimal;
};
The console.log
in the cellCurrencyFormat
does not fire at all.
For now, I've managed to get this working, by using <templates>
:
<paper-datatable-column header="amount" property="paymentAmount" align="right">
<template>
<span>{{cellCurrencyFormat(value)}}</span>
</template>
</paper-datatable-column>
With the cellCurrencyFormat
wrapper function local to the custom element.
Are you using the paper-datatable
inside of another custom element or inside of a dom-bind
? In the first case you need to define the value on the parent Polymer element and in the second case on the dom-bind
. Does this sound alien or is this exactly what you've been trying already?
@David-Mulder, it's inside a custom element. What do you mean by "define the value on the parent Polymer element"?
So you have something along the lines of
<dom-module>
<template>
<paper-datatable [...]>
<paper-datatable-column [...] format-value="{{cellCurrencyFormat}}"></paper-datatable-column>
</paper-datatable>
</template>
<script>
Polymer(
[...]
cellCurrencyFormat: function(){
[...]
}
);
</script>
</dom-module>
?
tal-ui-order-payment.html
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../content-widget/content-widget.html">
<link rel="import" href="../status-icon/status-icon.html">
<link rel="import" href="../progress-stepper/progress-stepper.html">
<link rel="import" href="../tal-ui-content-row/tal-ui-content-row.html">
<link rel="import" href="../../bower_components/byutv-jsonp/byutv-jsonp.html">
<link rel="import" href="../../bower_components/paper-datatable/paper-datatable.html">
<dom-module id="tal-ui-order-payment">
<template>
<style>
paper-datatable {
margin: 0px;
--paper-datatable-column-header: {
display: none;
}
--paper-datatable-divider-color: transparent;
--paper-datatable-cell: {
color: #000;
font-size: 0.9em;
font-weight: 400;
height: auto;
line-height: 1.1em;
white-space: nowrap;
padding: 2px 10px 2px 10px;
cursor: default;
}
}
</style>
<byutv-jsonp
auto
url="http://localhost:3030/orders/{{order-id}}/payment"
last-response="{{order}}"
handle-as="json"
loading="{{loading}}">
</byutv-jsonp>
<content-widget heading="payments and refunds" loading={{loading}}>
<progress-stepper steps="[[order.data.timeline]]"></progress-stepper>
<div class="content-container" hidden$="{{!order.data.payments}}">
<p class="section-heading">payments</p>
<paper-datatable data="{{order.data.payments}}">
<paper-datatable-column header="method" property="paymentType"></paper-datatable-column>
<paper-datatable-column header="amount" property="paymentAmount" align="right">
<template>
<span>{{_cellCurrencyFormat(value)}}</span>
</template>
</paper-datatable-column>
<paper-datatable-column header="status" property="paymentState">
<template>
<span>
<status-icon status="{{value}}"></status-icon>
</span>
</template>
</paper-datatable-column>
</paper-datatable>
</div>
<div class="content-container">
<p class="section-heading">authorization</p>
<tal-ui-content-row title="status" value-content="{{order.data.Auth}}" value-type="text" value-health="{{order.data.health.statusHealth}}"></tal-ui-content-row>
<tal-ui-content-row title="auth date" value-content="{{order.data.AuthDate}}" value-type="text" value-format="date" hidden$="{{!order.data.AuthDate}}"></tal-ui-content-row>
<tal-ui-content-row title="amount" value-content="{{order.data.Total}}" value-type="text" value-format="currency" hidden$="{{!order.data.Total}}"></tal-ui-content-row>
<tal-ui-content-row title="by" value-content="{{order.data.AuthUser}}" value-type="text" hidden$="{{!order.data.AuthUser}}"></tal-ui-content-row>
</div>
</content-widget>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'tal-ui-order-payment',
_cellCurrencyFormat: function (value) {
if (value != undefined) {
var cellFormat = formatCurrency (value, 'R ', 2);
return cellFormat;
}
}
});
})();
</script>
</dom-module>
extract from tal-ui-order-payment.html
function formatCurrency (value, currency, precision) {
if (value === undefined) {
return '';
};
if (isNaN(value)) {
return "Value is not a Number";
} else {
currency = currency || "$";
precision = precision || 2;
value = Number(value);
value = value.toFixed(precision);
}
var parts = value.split('.'),
fnum = parts[0],
decimal = parts[1] ? '.' + parts[1] : '';
return currency + fnum.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') + decimal;
};
Hmm, that indeed looks the way I would expect it to look. And I understand correctly that
<paper-datatable-column header="amount" property="paymentAmount" format-value="{{_cellCurrencyFormat}}" align="right"></paper-datatable-column>
didn't work?
No, this implementation is working now.
That's so odd, once I have access to my development environment I will check and try figuring out what could be happening.
Just ran into this myself. If you define the helper function like this it works in polymer 1:
<paper-datatable-column header="Size" property="Size" format-value="{{formatSize}}" >
Polymer({
properties: {
formatSize:{
type: Function,
value :function(){
return function(v){
var size = parseInt(v,10);
if(isNaN(size)){
return '';
}
return (size/1024/1024).toFixed(2) + " MB";
};
}
}
},
I just had to use the same fugly hack for filtering.
... i guess it works but it is horrible!
@JensGroenborg I'm struggling trying to apply a filter this way, could you please post your solution??
Sure, here is my little user admin page, for very unsecure intranet usage, hope you can make anything out of it, and if anybody figures out how to mark which rows has been updated in a paper-datatable i'm all ears.
The important parts are filter="{{filteredItems}}" and the filteredItems funciton which returns a function:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../bower_components/paper-datatable/paper-datatable.html">
<dom-module id="access-overrides">
<template>
<iron-ajax id="overrides" auto url="[[serviceUrl]]" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax id="overridesPost" url="[[serviceUrl]]" handle-as="json" method="post" body="{{users}}"></iron-ajax>
<div class="input-row">
<paper-input id="uid" label="User id" required="true" value="{{guid}}"
pattern="[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" error-message="Invalid pattern"
auto-validate></paper-input>
<paper-input id="role" label="Role" value="{{role}}"></paper-input>
<paper-toggle-button id="allow" checked="{{allow}}">Allow</paper-toggle-button>
<paper-input id="expiresAt" label="Expires At" value="{{expiresAt}}"></paper-input>
<div id="addRemovePanel">
<paper-button id="addOverride" raised on-click="addOverride">
<iron-icon icon="add"></iron-icon>
Add
</paper-button>
<paper-button id="removeOverride" raised on-click="removeOverrides">
<iron-icon icon="remove"></iron-icon>
Remove
</paper-button>
</div>
</div>
<div>
<paper-datatable id="overrideTable" data="{{users}}" filter="{{filteredItems}}" selectable multi-selection>
<paper-datatable-column header="User Id" property="uid" type="String" style="" sortable></paper-datatable-column>
<paper-datatable-column header="Role" property="role" type="String" style="" editable sortable></paper-datatable-column>
<paper-datatable-column header="Allow" property="allow" type="Boolean" style="" editable sortable></paper-datatable-column>
<paper-datatable-column header="Expires At" property="expiresAt" type="String" style="" default="" editable sortable></paper-datatable-column>
</paper-datatable>
</div>
<paper-button id="save" raised on-click="save">
<iron-icon icon="save"></iron-icon>
Gem
</paper-button>
</template>
<script>
Polymer({
is: 'access-overrides',
properties: {
serviceUrl: String,
users: Array,
filteredItems: { // Ugliest hack ever, but apparently necessary!
value: function() {
return function(user, event, items) {
return !user.remove;
}
}
}
},
save: function(event) {
var post = this.$.overridesPost;
post.contentType = "application/json";
post.generateRequest();
},
addOverride: function() {
var user = {'uid': this.$.uid.value, 'role': this.$.role.value, 'allow': this.$.allow.checked, 'expiresAt': this.$.expiresAt.value};
this.unshift('users', user);
},
removeOverrides: function(obj) {
this.$.overrideTable.selectedItems.forEach(function(u) {u.remove = true});
this.$.overrideTable.reload();
}
});
</script>
</dom-module>
For what it's worth, I came across this issue when having similar issues with a custom sort algorithm. Jonaz's solution did the trick for me.
I intend to redo the behavior of the sort
, filter
, format-value
function declaration to the following:
In <template is="dom-repeat">
the way they deal with 'outside' functions is by just putting the name of the function between as attribute like this <template filter="filterFunction">
. I suggest doing the same for all mentioned function types.
And I side of the Polymer Element you have to do some calculations as the eg filter
function changes:
properties: {
filter: {
type: Function,
observer: '_filterFunctionChanged'
}
},
function _filterFunctionChanged(filter) {
var dataHost = (this.dataHost && this.dataHost._rootDataHost) || this.dataHost;
this._filterFn = filter && (typeof filter == 'function' ? filter :
function() { return dataHost[filter].apply(dataHost, arguments); });
// Reload data
}