I have a meteor app using livestamp. However, I wish to represent a collection within a reactive-table. However, when I try the code below, it doesn't work (I see nothing in the updated column):
Template.sensor_table.helpers
settings: () ->
return {
collection: Sensors
rowsPerPage: 100
showFilter: true
fields: [
{ key: '_id', label: 'id' },
{ key: '_id', label: 'rack', fn: (v,o) -> (getSensor v).rack },
{ key: 'temp', label: 'temperature (degC)' },
{ key: 'ts', label: 'updated', fn: (v,o) -> livestamp v }
]
}
but when I use it within a template, it works fine. How can I get the functionality of livestamp within my reactive table?
You can do that with https://atmospherejs.com/aldeed/tabular it's also datatables but it's different package (in my opinion better)
if you choose to use it here is an example, tabular has the option to render fields as a template and livestamp should work just as on the template itself.
TabularTables.Books = new Tabular.Table({
name: "Books",
collection: Books,
columns: [
{data: "_id", title: "id"},
{data: "_id", title: "Rack"},
{ data: 'ts', title: 'updated',
tmpl: Meteor.isClient && Template.liveStamp
}
]
});
// template
<template name="liveStamp">
<p>{{livestamp this.ts}}</p>
</template>
so i guess it helps to actually read the manual....
Template.sensor_table.helpers
settings: () ->
return {
collection: Sensors
rowsPerPage: 100
showFilter: true
fields: [
{ key: '_id', label: 'id' },
{ key: '_id', label: 'rack', fn: (v,o) -> (getSensor v).rack },
{ key: 'temp', label: 'temperature (°C)' },
{ key: 'ts', label: 'updated', tmpl: Template.sensor_updated }
]
}
and then a template somewhere...
<template name="sensor_updated">
{{ livestamp ts }}
</template>
Related
I followed the example for onExpandRow, however I can't figure out how to use the row information that is passed with a url for my table instead of the data tag. Currently it just replicates my whole table in the expand function, not just the rows data. Probably a simple fix but I am missing it.
onExpandRow: function (index, row, $detail) {
console.log(row)
$detail.html('<table></table>').find('table').bootstrapTable({
url: 'table.php',
columns:[{
field: 'mfr_name',
title: 'manufacturer'},
{field: 'phone_number',
title: 'phone'},
],
})
The example has the data saved in a variable and uses the data: call instead of the url: one.
var data = [{
'col1': '1.1',
'col2': '1.2',
'nested': [{
'col3': '1.3',
'col4': '1.4',
'col5': '1.5'
}]
onExpandRow: function(index, row, $detail) {
console.log(row)
$detail.html('<table></table>').find('table').bootstrapTable({
clickToSelect: true,
columns: [{
field: 'select',
checkbox: true
}, {
field: 'col3',
title: 'Col3'
}, {
field: 'col4',
title: 'Col4'
}, {
field: 'col5',
title: 'Col5'
}],
data: row.nested,
Did you mean something like this:
http://jsfiddle.net/eitanmg/m41ok0ue/12/
The main change is when expanding the row, it will make AJAX call to get the data you want from remote resource and not from local variable.
$(function () {
$('#table').bootstrapTable({
data: data,
detailView:true,
onExpandRow: function (index, row, $detail) {
$detail.html('Loading request...');
$.ajax({
type: "GET",
url: "/your_custom_url_that_contains_the_data",
success: function (result) {
$detail.html('<table></table>').find('table').bootstrapTable({
columns: [{
field: 'select',
checkbox: true
}, {
field: 'col1',
title: 'Col1'
}, {
field: 'col2',
title: 'Col2'
}, {
field: 'col3',
title: 'Col3'
}],
data: JSON.parse(result),
});
}
});
}
});
});
I'm trying to do the autoform books example using Meteor. How exactly should I do the Books.insert ?
I see the example:
Books.insert({title: "Ulysses", author: "James Joyce"}, function(error, result) {
//The insert will fail, error will be set,
//and result will be undefined or false because "copies" is required.
//
//The list of errors is available on
//`error.invalidKeys` or by calling
Books.simpleSchema().namedContext().invalidKeys()
});
I'm not entirely sure how I should hook this up with the rest of my code:
if (Meteor.isClient) {
Books = new Meteor.Collection("books");
var Schemas = {};
Schemas.Book = new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200,
optional: true
},
author: {
type: String,
label: "Author",
optional: true
},
copies: {
type: Number,
label: "Number of copies",
min: 0,
optional: true
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
});
Books.attachSchema(Schemas.Book);
}
Can anyone give me any advice on this?
I'm thinking that I would need something like this:
Template.bookform.events({
'click btn.submit': function () {
var form = document.getElementById("formID").value;
Books.insert(form);
}
});
Thanks in advance! :)
I have never used autoform but in the documentation it says that it already gives you "automatic insert and update events, and automatic reactive validation".
So there should be no need to specify your own event handler.
In the docs you will also find the books example. I am just copying from there:
JS
Books = new Meteor.Collection("books", {
schema: {
title: {
type: String,
label: "Title",
max: 200
},
author: {
type: String,
label: "Author"
},
copies: {
type: Number,
label: "Number of copies",
min: 0
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
}
});
if (Meteor.isClient) {
Meteor.subscribe("books");
}
if (Meteor.isServer) {
Meteor.publish("books", function () {
return Books.find();
});
}
HTML
<head>
<title>Book example</title>
</head>
<body>
{{> insertBookForm}}
</body>
<template name="insertBookForm">
{{> quickForm collection="Books" id="insertBookForm" type="insert"}}
</template>
I have tried various ways to refresh the grid but everything I try doesn't work. Do I refresh the Grid or do I load the store??? You can see that the paging tool bar is still showing 50 pages after the filtering. If there are no dates on a given pag and it is empty then it will disable the tool bar and paging doesn't work after that page un less you refresh the browser and skip over the empty page. So, in my case page 15 has no rows so it breaks when u hit next and get that page. If you type in the page number 16 then all is good until you hit another's empty page.
My datepicker is in my viewport below and I have tried refreshing the gird and loading the store as well as other things which mostly result in undefined error. Not sure where to start with this one so I will show my code and screen shots below:
BEFORE DATE SELECTION:
AFTER DATE SELECTION:
STORE:
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'AM.model.User',
autoLoad: true,
autoSync:true,
pageSize:50,
proxy:
{
type: 'ajax',
//extraParams :{limit:1000},
api:
{
read: 'http://192.168.0.103/testit/dao_2.cfc?method=getContent',
update: 'http://192.168.0.103/testit/dao_2-post.cfc?method=postContent'
},
reader:
{
type: 'json',
root: 'data',
successProperty: 'success',
totalProperty : 'dataset',
remoteFilter : true
},
listeners:
{
// stuff goes here maybe??
}
}
});
GRID PANEL:
Ext.define('AM.view.user.List' ,{
extend: 'Ext.grid.Panel',
alias: 'widget.userlist',
title: 'All Users',
store: 'Users',
//buffered: true,
plugins:[Ext.create('Ext.grid.plugin.RowEditing', {clicksToEdit: 2})],
dockedItems: [{ xtype: 'pagingtoolbar',
store: 'Users',
dock: 'bottom',
displayMsg: 'Displaying Records {0} - {1} of {2}',
displayInfo: true}],
initComponent: function() {
this.columns = [
Ext.create('Ext.grid.RowNumberer',
{
resizable: true,
resizeHandles:'all',
align: 'center',
minWidth: 35,
maxWidth:50
}),
{
header: 'Name',
dataIndex: 'message_id',
flex: 1,
editor:'textfield',
allowBlank: false,
menuDisabled:true
},
{
header: 'Email',
dataIndex: 'recip_email',
flex: 1,
editor:'textfield',
allowBlank: false,
menuDisabled:true
},
{
header: 'Date Time',
dataIndex: 'unix_time_stamp',
width: 120,
menuDisabled:true,
// submitFormat: 'd/m/Y',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
field:{ xtype:'datefield',
autoSync:true,
allowBlank:false,
editor: new Ext.form.DateField(
{format: 'm/d/y'}) }
}];
this.callParent(arguments);
},
});
VIEWPORT:
Ext.Loader.setConfig({enabled:true});
Ext.application({
requires: ['Ext.container.Viewport'],
name: 'AM',
appFolder: 'app',
controllers: ['Users'],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'border',
items:[{
region: 'center',
itemId:'centerPanelRegion',
title:'The Title',
xtype: 'tabpanel',
hidden: true,
activeTab: 0,
items:[{
xtype: 'userlist',
listeners:
{
select: function(selModel, record, index, options)
{
// do something with the selected date
console.log('select');
},
add: function(selModel)
{
// do something with the selected date
console.log('add - init2.js');
},
afterrender:function(selModel)
{
// do something with the selected date
console.log('afterrender - userlist(init2.js)');
},
beforerender:function(selModel)
{
// do something with the selected date
console.log('beforerender - userlist(init2.js)');
}
}
}]
},
{
region: 'west',
itemId:'westPanelRegion',
hidden: true,
layout:'fit',
xtype: 'tabpanel',
activetab:0,
collapsible:false,
split: false,
title: 'The Title',
width:178,
maxWidth:400,
height: 100,
minHeight: 100,
items:[{
title: 'Tab 1',
xtype:'panel',
items:
[{
xtype: 'datepicker',
itemId:'datePickerFld',
listeners:{
beforerender: function(){
console.log('datepicker - beforerender(init2.js)');
var store = Ext.getStore('dates');
store.load({callback: function(){
console.log('datepicker - callback(init2.js');
console.log(store.data.items[999].data.recip_email);
console.log(store.data.items[999].data.unix_time_stamp);
}
})
}
},
handler: function(picker, date)
{
// do something with the selected date
console.log('date picker example in init2.js' + Ext.Date.format(date,'m/d/Y'));
// get store by unique storeId
var store = Ext.getStore('Users');
// clear current filters
store.clearFilter(true);
// filter store
Ext.encode(store.filter("unix_time_stamp", Ext.Date.format(date,'m/d/Y')));
//store.load();
//store.sync();
}
}]
},
{
title: 'Tab 2',
html: 'ers may be added dynamically - Others may be added dynamically',
}]
}]
});
}
});
CONTROLLER:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
stores:['Users', 'dates'],
models:['User', 'date'],
views: ['user.List','user.Edit'],
init: function() {
Ext.getStore('dates').addListener('load',this.ondatesStoreLoad, this);
this.control(
{
'viewport > userlist':
{
itemdblclick: this.editUser,
},
'useredit button[action=save]':
{
click: this.updateUser
}
});
},
// ---------- handler Function declarations -------------
ondatesStoreLoad: function(me,records,success)
{
// ------ Gets the dates from dates store and loads an array
var store = this.getStore('dates');
sendDataArray = [];
store.each(function(record){
var recordArray = [record.get("unix_time_stamp")];
sendDataArray.push(recordArray);
});
// ------ Set DatePicker Bullshit right fucking here --------//
var dtFld = Ext.ComponentQuery.query('#datePickerFld')[0];
dtFld.setDisabledDates(["^(?!"+sendDataArray.join("|")+").*$"]);
dtFld.setMaxDate(new Date());
dtFld.setMinDate(new Date('05/01/2013'));
var wstPnlReg = Ext.ComponentQuery.query('#westPanelRegion')[0];
wstPnlReg.show();
var ctrPnlReg = Ext.ComponentQuery.query('#centerPanelRegion')[0];
ctrPnlReg.show();
// var grid = Ext.widget('userlist');
},
onUsersStoreDataChange: function(me)
{
//console.log('Hey the store data just changed!');
},
editUser: function(grid, record)
{
var view = Ext.widget('useredit');
view.down('form').loadRecord(record);
},
updateUser: function(button)
{
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
},
});
UPDATED VIEWPORT: Changes made only in datepicker handler
Ext.Loader.setConfig({enabled:true});
Ext.application({
requires: ['Ext.container.Viewport'],
name: 'AM',
appFolder: 'app',
controllers: ['Users'],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'border',
items:[{
region: 'center',
itemId:'centerPanelRegion',
title:'The Title',
xtype: 'tabpanel',
hidden: true,
activeTab: 0,
items:[{
xtype: 'userlist',
listeners:
{
select: function(selModel, record, index, options)
{
// do something with the selected date
console.log('select');
},
add: function(selModel)
{
// do something with the selected date
console.log('add - init2.js');
},
afterrender:function(selModel)
{
// do something with the selected date
console.log('afterrender - userlist(init2.js)');
},
beforerender:function(selModel)
{
// do something with the selected date
console.log('beforerender - userlist(init2.js)');
}
}
}]
},
{
region: 'west',
itemId:'westPanelRegion',
hidden: true,
layout:'fit',
xtype: 'tabpanel',
activetab:0,
collapsible:false,
split: false,
title: 'The Title',
width:178,
maxWidth:400,
height: 100,
minHeight: 100,
items:[{
title: 'Tab 1',
xtype:'panel',
items:
[{
xtype: 'datepicker',
itemId:'datePickerFld',
listeners:{
beforerender: function(){
console.log('datepicker - beforerender(init2.js)');
var store = Ext.getStore('dates');
store.load({callback: function(){
console.log('datepicker - callback(init2.js');
console.log(store.data.items[999].data.recip_email);
console.log(store.data.items[999].data.unix_time_stamp);
}
})
}
},
handler: function(picker, date)
{
// do something with the selected date
console.log('date picker example in init2.js' + Ext.Date.format(date,'m/d/Y'));
// get store by unique storeId
var store = Ext.getStore('Users');
// clear current filters
store.clearFilter(true);
// filter store
store.filter("unix_time_stamp", Ext.Date.format(date,'m/d/Y'));
// Load the store
store.load();
}
}]
},
{
title: 'Tab 2',
html: 'ers may be added dynamically - Others may be added dynamically',
}]
}]
});
}
});
This line is likely causing the issues.
Ext.encode(store.filter("unix_time_stamp", Ext.Date.format(date,'m/d/Y')));
I'm not sure why you are calling Ext.encode on whatever store.filter returns, but I don't think you want to do that (and it is likely causing the undefined errors).
As for the paging toolbar not updating the current count, it is likely you just aren't returning the correct information in your server response when updating the store. The server response should include the total number of records. According to the docs for Ext.toolbar.Paging, http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.toolbar.Paging:
The packet sent back from the server would have this form:
{
"success": true,
"results": 2000,
"rows": [ // ***Note:** this must be an Array
{ "id": 1, "name": "Bill", "occupation": "Gardener" },
{ "id": 2, "name": "Ben", "occupation": "Horticulturalist" },
...
{ "id": 25, "name": "Sue", "occupation": "Botanist" }
]
}
I want to get belongsTo record on datalist and show parent record fields.
Ext.define('MyApp.model.Customer', {
extend: 'Ext.data.Model',
config: {
fields: ['Id',
'EMail'],
hasMany: [{
model: 'MyApp.model.OutstandingInvoice',
name: 'OutstandingInvoice',
primaryKey: 'Id',
foreignKey: 'customerId',
foreignStore: 'OutstandingInvoices'
}]
}
});
Ext.define('MyApp.model.OutstandingInvoice', {
extend: 'Ext.data.Model',
config: {
fields: [
'InvoiceDate',
'InvoiceID',
'customerId'
],
belongsTo: [{
model: 'MyApp.model.Customer',
name: 'Customer',
primaryKey: 'Id',
foreignKey: 'customerId',
foreignStore: 'Customers'
}]
}
});
Ext.define('MyApp.store.OutstandingInvoices', {
extend: 'Ext.data.Store',
config: {
model: 'MyApp.model.OutstandingInvoice',
storeId: 'OutstandingInvoiceStore',
proxy: {
useDefaultXhrHeader: false,
type: 'ajax',
url : 'http://localhost/getOutstandingInvoices',
reader: {
type: 'json'
}
},
autoLoad: false
}
});
Ext.define('MyApp.store.Customers', {
extend: 'Ext.data.Store',
config: {
model: 'MyApp.model.Customer',
storeId: 'CustomerStore',
proxy: {
useDefaultXhrHeader: false,
type: 'ajax',
url : 'http://localhost/getCustJList',
reader: {
type: 'json'
}
},
autoLoad: false,
sorters: [{
property : 'FName',
direction: 'ASC'
}]
}
});
Ext.define('MyApp.view.OutstandingInvoices', {
extend: 'Ext.Panel',
xtype: 'outstandingInvoicesXType',
config: {
cls : 'invoiceSummaryCls',
scrollable: 'vertical',
items: [
{
xtype: 'titlebar',
docked: 'top',
title: 'Outstanding Invoices'
},
{
xtype : 'list',
scrollable: false,
store: 'OutstandingInvoiceStore',
cls : 'p10',
itemTpl: [
'<div>Invoice # {InvoiceID}</div>',
'<div>{InvoiceDate}</div>',
'<div>{Customer.Email}</div>', // I want to show Customer name here as its belongsTo Customer
],
listeners: {
itemtap:function (list, index, targe, rec, e, eOpts) {
console.log(rec)
}
}
}
]
}
});
I want to show Customer name in datalist but having issue with association or Xtemplate
I am getting this error
Uncaught Error: [ERROR][Ext.XTemplate#apply] Cannot read property 'Email' of undefined
Please help me out in this.
I'd recommend reading this article, its quite lengthy but the final List section is similar to your example.
I think the key point is you're not going to need separate stores. Sencha is going to create those automatically off the back of the associations. Make sure you move the proxies onto the models and set autoLoad: true
I want to populate the combobox dynamically based on the data I received from thr Url(which is servlet)
Below is my ExtJS code :
{
xtype:'combo',
id: 'shoutoutsTags',
fieldLabel: 'Tag',
value: '',
mode: 'local',
width: 200,
store: new Ext.data.JsonStore({
id:'ms',
url:'http://localhost:8080/ezdi/extServlet',
//totalProperty:'totalCount',
root:'rows',
fields:[
{name:'un'},
{name:'pwd'}
],
autoLoad:true
}),
displayField: 'un',
valueField: 'pwd',
typeAhead:true,
minChars:1,
forceSelection: true,
triggerAction: 'all',
hideTrigger:true
//hiddenName: 'mytag'
}
But I am getting below error and my Url is not being called:
msg : "You are using a ServerProxy but have not supplied it with a url."
sourceClass : "Ext.data.proxy.Server"
sourceMethod : "buildUrl" uncaught exception: You are using a ServerProxy
but have not supplied it with a
url.
Suggest me how can I overcome this error.
Ext.define("modelname", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url : '/myServlet',
method:'POST',
reader: {
type: 'json',
root: 'rows'
//,totalProperty: 'totalCount'
}
},
fields: [
{name: 'name', mapping: 'name'}
]
});
var ds = Ext.create('Ext.data.Store', {
pageSize: 10,
model: 'modelName'
});
Your store needs to be updated to use the new Ext JS 4 data model:
var store = Ext.create('Ext.data.Store', {
model: 'MyNamespace.StoreModel',
proxy: {
type: 'ajax',
url: 'http://localhost:8080/ezdi/extServlet',
reader: {
type: 'json',
root: 'rows',
totalProperty: 'totalCount'
}
}
});
You'll notice here that the store has a property 'model', which is a string, and that there is no field mapping. This is because you'll also need to create a model for the store to reference, like so:
Ext.define('MyNamespace.StoreModel', {
extend: 'Ext.data.Model',
fields: [
{name:'un'},
{name:'pwd'}
]
});
Hope this helps!
Thats not a valid url, you'll want just '/ezdi/extServlet'.