Adapt React.createClass method to ES6 Class Component with react-data-grid - javascript

I am working the react-data-grid library to create an filterable datatable in react. All of their examples use the depreciated React.createClass method, and I am trying to refactor to the ES6 Class Components.
Specifically, I am trying to refactor the Filterable Grid example:
demo
source
gist of non-refactored adaption that is working
My refactored code looks like this:
import React from 'react'
import ReactDataGrid from 'react-data-grid'
const { Toolbar, Data: { Selectors } } = require('react-data-grid-addons')
class FilterableTable extends React.Component {
constructor(props) {
super(props);
this._columns = [
{
key: 'id',
name: 'ID',
width: 80
},
{
key: 'task',
name: 'Title',
editable: true
},
{
key: 'priority',
name: 'Priority',
editable: true
},
{
key: 'issueType',
name: 'Issue Type',
editable: true
},
{
key: 'complete',
name: '% Complete',
editable: true
},
{
key: 'startDate',
name: 'Start Date',
editable: true
},
{
key: 'completeDate',
name: 'Expected Complete',
editable: true
}
];
this.state = { rows: this.createRows(1001), filters: {} };
console.log(this.state);
}
getRandomDate = (start, end) => {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toLocaleDateString();
}
createRows = () => {
let rows = [];
for (let i = 1; i < 1000; i++) {
rows.push({
id: i,
task: 'Task ' + i,
complete: Math.min(100, Math.round(Math.random() * 110)),
priority: ['Critical', 'High', 'Medium', 'Low'][Math.floor((Math.random() * 3) + 1)],
issueType: ['Bug', 'Improvement', 'Epic', 'Story'][Math.floor((Math.random() * 3) + 1)],
startDate: this.getRandomDate(new Date(2015, 3, 1), new Date()),
completeDate: this.getRandomDate(new Date(), new Date(2016, 0, 1))
});
}
return rows;
}
getRows = () => {
return Selectors.getRows(this.state);
}
getSize = () => {
return this.getRows().length;
}
rowGetter = ( rowIdx ) => {
let rows = this.getRows();
return rows[rowIdx];
}
handleFilterChange = ({ filter }) => {
let newFilters = Object.assign({}, this.state.filters);
if (filter.filterTerm) {
newFilters[filter.column.key] = filter;
} else {
delete newFilters[filter.column.key];
}
this.setState({ filters: newFilters });
}
onClearFilters = () => {
// all filters removed
this.setState({filters: {} });
}
render() {
return (
<ReactDataGrid
columns={this._columns}
rowGetter={this.rowGetter}
enableCellSelect={true}
rowsCount={this.getSize()}
minHeight={800}
toolbar={<Toolbar enableFilter={true}/>}
onAddFilter={this.handleFilterChange}
onClearFilters={this.onClearFilters} />);
}
}
export default FilterableTable
Issue:
An issue arises when I click the filter button - a new header row is rendered (via the Toolbar component), but there is no input field. This screenshot shows the two examples side by side - my ES6 version on top and the createClass version on the bottom:
I am not sure what is causing this, but have a feeling it might be due to the way I am importing Toolbar ? Any help or a point in the right direction would be greatly appreciated ! (As well as any other suggestions re refactoring this component.)

To enable filtering for a given column, you need to set filterable=true for that column. So, add filterable:true to each object in this._columns. For more info, check http://adazzle.github.io/react-data-grid/examples.html#/filterable-grid.
this._columns = [
{
key: 'id',
name: 'ID',
width: 80
},
{
key: 'task',
name: 'Title',
editable: true,
filterable:true
},
{
key: 'priority',
name: 'Priority',
editable: true,
filterable:true
},
{
key: 'issueType',
name: 'Issue Type',
editable: true,
filterable:true
},
{
key: 'complete',
name: '% Complete',
editable: true,
filterable:true
},
{
key: 'startDate',
name: 'Start Date',
editable: true,
filterable:true
},
{
key: 'completeDate',
name: 'Expected Complete',
editable: true,
filterable:true
}
];

Related

JQuery Query-Builder adding autocomplete plugin

I'm using jquery-querybuilder to build out a query. I'm currently having an issue with adding in selectize as a plugin to allow for autocomplete inside the select inputs. I'm logging the data in the for loop and it prints out the correct data so I know its physically getting the data, but when typing in the input box, there is still no autocomplete and I'm not quite sure where I went wrong.
let totalMachines = [];
var rules_basic = {
condition: 'AND',
rules: [{
}, {
condition: 'OR',
rules: [{
}, {
}]
}]
};
let options = {
plugins: [],
allow_empty: true,
filters: [
{
id: 'machineName',
label: 'Machine Name',
type: 'string',
input: 'text',
operators: ['equal'],
plugin: 'selectize',
values: {
},
plugin_config: {
valueField: 'id',
labelField: 'machineName',
searchField: 'machineName',
sortField: 'machineName',
create: false,
maxItems:3,
plugins: ['remove_button'],
onInitialize: function() {
var that = this;
totalMachines.forEach(function(item) {
that.addOption(item);
console.log(item)
});
}
},
valueSetter: function(rule, value) {
rule.$el.find('.rule-value-container input')[0].selectize.setValue(value);
}
},
]
}
$.ajax({
url: '/api-endpoint',
type: 'GET',
contentType: 'application/json',
dataType: 'json',
success: function(response){
console.log(response)
response.forEach((res) => {
totalMachines.push(res[0])
})
console.log(totalMachines)
}
})
.then(() => {
// Fix for Selectize
$('#builder').on('afterCreateRuleInput.queryBuilder', function(e, rule) {
if (rule.filter.plugin == 'selectize') {
rule.$el.find('.rule-value-container').css('min-width', '200px')
.find('.selectize-control').removeClass('form-control');
}
});
$('#builder').queryBuilder(options)
})
It would be extremely helpful if someone could help me figure out how to properly configure this plugin, I've looked at every thread and haven't been able to figure it out.
Here is a simple example, using a local datasource, the namesList array
<script>
$(document).ready(function() {
let namesList = [{ id: '1', name: 'andrew' }, { id: '2', name: 'bob' }, { id: '3', name: 'charles' }, { id: '4', name: 'david' }];
let pluginConfig = {
preload: true,
valueField: 'id',
labelField: 'name',
searchField: 'name',
options: namesList,
items: ['2'],
allowEmptyOption: true,
plugins: ['remove_button'],
onInitialize: function () { },
onChange: function (value) {
console.log(value);
},
valueSetter: function (rule, value) {
rule.$el.find('.rule-value-container input')[0].selectize.setValue(value);
},
valueGetter: function (rule) {
var val = rule.$el.find('.rule-value-container input')[0].selectize.getValue();
return val.split(',');
}
}
let filterList = [{
id: 'age',
type: 'integer',
input: 'text'
},
{
id: 'id',
label: 'name',
name: 'name',
type: 'string',
input: 'text',
plugin: 'selectize',
plugin_config: pluginConfig
}];
let options = {
allow_empty: true,
operators: ['equal', 'not_equal', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
filters: filterList
}
$('#builder').queryBuilder(options);
// Fix for Selectize
$('#builder').on('afterCreateRuleInput.queryBuilder', function (e, rule) {
if (rule.filter.plugin == 'selectize') {
rule.$el.find('.rule-value-container').css('min-width', '200px').find('.selectize-control').removeClass('form-control');
}
});
});

chaining multiple filters in vuex getters

I have a building list. I am able to fetch the building data into component by storing it into building list state.
There are multiple dropdownlist as a different filters(e.g: status, state, country etc). I want to chain up all the filters and getting filtered data.
Here is the faker data regarding filter structure
const buildingFilters = {
fields: [
{
field: 'id',
title: 'Id',
},
{
field: 'name',
title: 'Name',
},
{
field: 'type',
title: 'Type'
},
{
field: 'status',
title: 'Status'
},
{
field: 'city',
title: 'City'
},
{
field: 'state',
title: 'State'
},
{
field: 'country',
title: 'Country'
},
{
field: 'reporting Zone',
type: 'Reporting Zone'
}
],
filtersType: {
country: {
field: 'country',
listofValues: ['USA', 'CANADA']
},
state: {
field: 'state',
listofValues: ['Maryland', 'New Jersey']
},
city: {
field: 'city',
listofValues: ['Bethesda', 'Monmoth Junction']
},
reporting_zone: {
field: 'reporting_zone',
listofValues: ['RZ1', 'RZ2']
},
status: {
field: 'status',
listofValues: ['Draft', 'Inprogress']
},
type: {
field: 'type',
listofValues: ['Type 1', 'Type 2']
}
}
Now, i am calling this by service to load the initial filters into component. Now,i have to configure it into store.
const defaultState = {
bldgList: emptyArray,
bldgFilter: emptyArray,
filteredData: [],
filterTypes: {
filterByStatus: '',
filterByCountry: '',
filterByState: ''
}
};
const getters = {
filteredData: state => {
return state.filteredData = state.bldgList.slice()
if(state.filterTypes.filterByStatus !== '') {
// not understand how will i do that
}
}
};
const mutations = {
FILTER_FIELD_CHANGE(state,payload) {
// here we need to update Filters change
}
},
const actions = {
async filteredData({commit}, filterTypes) {
commit('FILTER_FIELD_CHANGE', filterTypes)
}
}
This store is not correct i know but how to filter building list based on multiple different filters and chaining filters based on condition.
The getter could call Array.prototype.filter() on the input based on the given filters, one by one. The following example assumes filterByStatus, filterByCountry and filterByState each contain the search term.
const getters = {
filteredData: state => {
let bldgs = state.bldgList
if (state.filterTypes.filterByStatus) {
bldgs = bldgs.filter(b => b.status.includes(state.filterTypes.filterByStatus))
}
if (state.filterTypes.filterByCountry) {
bldgs = bldgs.filter(b => b.country === state.filterTypes.filterByCountry)
}
if (state.filterTypes.filterByState) {
bldgs = bldgs.filter(b => b.state === state.filterTypes.filterByState)
}
return bldgs
}
};

Javascript: Create a form with a parametric number of textbox (TinyMCE)

I am not a Web developer, I have to do just a small task once, but I hate copy & paste.
Look at the code below, I'd like to avoid copy and paste (question1, question2 ,..., question[i]). I'd like to create a for statement but I should handle properties with a dynamic name. In c# I would use reflection or dynamic.
Is it possible in Javascript? Is it the correct approach? Should I dynamically generate the code and use Eval()?
tinymce.PluginManager.add('test_containers', function(editor, url) {
editor.addButton('test_containers2', {
title: 'Container 2',
text: 'Container 2',
onclick: function() {
editor.windowManager.open({
title: 'Test Container',
body: [{
type: 'container',
layout: 'stack',
columns: 2,
minWidth: 500,
minHeight: 500,
items: [{
type: 'textbox',
name: 'question1'
}, {
type: 'textbox',
name: 'question2'
}, ]
}],
onsubmit: function(e) {
ed.insertContent(e.data.question1 + e.data.question2);
}
});
}
});
});
tinymce.init({
selector: '#mytextarea',
plugins: 'colorpicker test_containers',
toolbar: 'test_containers2'
});
// Taken from core plugins
var editor = tinymce.activeEditor;
function createColorPickAction() {
var colorPickerCallback = editor.settings.color_picker_callback;
if (colorPickerCallback) {
return function() {
var self = this;
colorPickerCallback.call(
editor,
function(value) {
self.value(value).fire('change');
},
self.value()
);
};
}
}
<script src="https://cdn.tinymce.com/4/tinymce.min.js"></script>
<textarea id="mytextarea">Hello, World!</textarea>
See: https://jsfiddle.net/Revious/gm2phuva/3/
From my understanding, you need to add the items dynamically.
I have added two function on your code.
createArr -> will create the array of list of the specified number (n)
handleQuesData -> will concat the data of all the questions and pass it to onsubmit function
tinymce.PluginManager.add('test_containers', function(editor, url) {
// item creation dynamically
let createArr = (n) => {
let arr = []
for (let i = 0; i < n; i++) {
arr.push({
type: 'textbox',
name: `question{i+1}`
})
}
return arr;
}
// onsubmit handled dynamically
let handleQuesData = (data, n) => {
let quesdata = ''
for (let i = 0; i < n; i++) {
quesdata += data[`question{i+1}`]
}
return quesdata
}
let numItem = 2;
editor.addButton('test_containers2', {
title: 'Container 2',
text: 'Container 2',
onclick: function() {
editor.windowManager.open({
title: 'Test Container',
body: [{
type: 'container',
layout: 'stack',
columns: 2,
minWidth: 500,
minHeight: 500,
items: createArr(numItem)
}],
onsubmit: function(e) {
ed.insertContent(handleQuesData(e.data, numItem));
}
});
}
});
});
tinymce.init({
selector: '#mytextarea',
plugins: 'colorpicker test_containers',
toolbar: 'test_containers2'
});
// Taken from core plugins
var editor = tinymce.activeEditor;
function createColorPickAction() {
var colorPickerCallback = editor.settings.color_picker_callback;
if (colorPickerCallback) {
return function() {
var self = this;
colorPickerCallback.call(
editor,
function(value) {
self.value(value).fire('change');
},
self.value()
);
};
}
}
Here is the demo code : JSFiddle
Hope it helps :)
Yes, you can dynamically generate the list of items.
tinymce.PluginManager.add('test_containers', function(editor, url) {
const totalQuestions = 10;
let questions = [];
for (let i = 1; i < totalQuestions; i++) {
questions.push({
type: 'textbox',
name: 'question' + i
});
}
editor.addButton('test_containers2', {
title: 'Container 2',
text: 'Container 2',
onclick: function() {
editor.windowManager.open({
title: 'Test Container',
body: [{
type: 'container',
layout: 'stack',
columns: 2,
minWidth: 500,
minHeight: 500,
items: questions
}],
onsubmit: function(e) {
ed.insertContent(e.data.question1 + e.data.question2);
}
});
}});
});
//......

Adding new row to grid

I require a Kendo Grid for the user to enter 'n' number of results, then click a button (seperate from the grid control) which will take all the results added to the grid and save them to the database. This should be a simple task considering there are no CRUD operations going on with the grid itself except to add additional, blank rows for data entry...
HOWEVER,
The problem is that the content of the grid is not static and can vary in column size (from 1 to 6) based on user input (my example shows how this will be represented in the form of an array Lots). It seems that most if not all tutorials available seem to focus solely on static content with very little help when it comes to anything else.
So far (with some feedback from Telerik) I have come up with the following...
Set up a Lot Schema i.e. a placeholder for all the data for each Lot in the array:
var Lots = [];
Lots.push({ ID: 13, LotNumber: "158UL" }),
Lots.push({ ID: 14, LotNumber: "646UE" });
var LotResultsSchema = [];
for (var p = 0; p < Lots.length; ++p) {
LotResultsSchema.push({
Result: {
Count: '',
Mean: '',
SD: ''
}
});
}
Set up the overall grid Schema Model ID:
var schemaModel = kendo.data.Model.define({
id: "ID",
fields: {
ID: { editable: false, nullable: true },
ResultDateTime: {
type: "date", validation: {
required: true
}
},
LotResults: LotResultsSchema,
StandardComment: {
ID: {
nullable: true, validation: {
required: false
}
},
Description: {
defaultValue: "<empty>",
validation: {
required: false
}
}
},
ReviewComment: {
ID: {
nullable: true, validation: {
required: false
}
},
Description: {
defaultValue: "<empty>",
validation: {
required: false
}
}
}
}
});
Set up the datasource for the grid based on the schema above:
var gridConfigDataSourceAdd = new kendo.data.DataSource({
data: [],
schema: {
model: schemaModel
}
});
Set up the column schema (again taking into account that there can be multiple columns created based on array size):
var columnSchema = [];
columnSchemaAdd.push({ field: "ResultDateTime", format: "{0:yyyy/MM/dd hh:mm:ss}", editor: dateTimeEditor, title: 'Date Time' });
for (var j = 0; j < Lots.length; ++j) {
columnSchemaAdd.push({
title: Lots[j].LotNumber,
field: Lots[j].ID,
columns: [{
field: "LotResults[" + j + "].Result.Count",
title: 'Count'
}, {
field: "LotResults[" + j + "].Result.Mean",
title: 'Mean'
}, {
field: "LotResults[" + j + "].Result.SD",
title: 'SD'
}]
});
}
columnSchemaAdd.push({ field: "StandardComment", title: 'Comment', editor: standardCommentDropDownEditor, template: "#=StandardComment.Description#" });
columnSchemaAdd.push({ field: "ReviewComment", title: 'Review Comment', editor: reviewCommentDropDownEditor, template: "#=ReviewComment.Description#" });
columnSchemaAdd.push({ command: ["edit", "destroy"] });
Set up the overall grid:
$("#configAddGrid").kendoGrid({
dataSource: gridConfigDataSourceAdd,
height: 550,
navigatable: true,
autoBind: false,
editable: {
mode: "inline"
},
toolbar: ["create"],
columns: columnSchemaAdd
});
Running this code and clicking the 'Add New' button to create a new row produces the following error:
Uncaught TypeError: Cannot read property 'Result' of undefined
I understand why I am getting this error, due to the new item being created with undefined LotResults. What I can't understand is how this can happen when the default values are being set up in the Lot Schema.
Any advice is appreciated, I am hoping someone has used Kendo Grids for the same purpose before as I would really like to get a look at an example which works!
I think the problem is with LotResultsSchema. Instead of creating it as a separate array, can try to merge it to the fields class?
<script>
var Lots = [];
Lots.push({ ID: 13, LotNumber: "158UL" }),
Lots.push({ ID: 14, LotNumber: "646UE" });
var fields1 = {
ID: { editable: false, nullable: true },
ResultDateTime: {
type: "date", validation: {
required: true
}
},
StandardComment: {
ID: {
nullable: true, validation: {
required: false
}
},
Description: {
defaultValue: "<empty>",
validation: {
required: false
}
}
},
ReviewComment: {
ID: {
nullable: true, validation: {
required: false
}
},
Description: {
defaultValue: "<empty>",
validation: {
required: false
}
}
}
};
for (var p = 0; p < Lots.length; ++p) {
fields1['Count' + Lots[p].ID] = {type : "number"};
fields1['Mean'+Lots[p].ID] = {type : "number"};
fields1['SD' +Lots[p].ID] = {type : "number"};
}
var schemaModel = kendo.data.Model.define({
id: "ID",
fields: fields1
});
var gridConfigDataSourceAdd = new kendo.data.DataSource({
data: [],
schema: {
model: schemaModel
}
});
var columnSchemaAdd = [];
columnSchemaAdd.push({ field: "ResultDateTime", format: "{0:yyyy/MM/dd hh:mm:ss}", title: 'Date Time' });
for (var j = 0; j < Lots.length; ++j) {
columnSchemaAdd.push({
title: Lots[j].LotNumber,
field: Lots[j].ID,
columns: [{
field: 'Count' + Lots[j].ID ,
title: 'Count'
},
{
field: 'Mean'+Lots[j].ID ,
title: 'Mean'
}, {
field: 'SD' + Lots[j].ID ,
title: 'SD'
}]
});
}
columnSchemaAdd.push({ field: "StandardComment", title: 'Comment', template: "#=StandardComment.Description#" });
columnSchemaAdd.push({ field: "ReviewComment", title: 'Review Comment', template: "#=ReviewComment.Description#" });
columnSchemaAdd.push({ command: ["edit", "destroy"] });
$("#configAddGrid").kendoGrid({
dataSource: gridConfigDataSourceAdd,
height: 550,
navigatable: true,
autoBind: false,
editable: {
mode: "inline"
},
toolbar: ["create"],
columns: columnSchemaAdd
});
</script>
A sample http://dojo.telerik.com/uHucA

Accessing Android phone contacts with phonegap and Sencha Touch

please I'm trying to get a list of all the contacts on my phone with the following code.
var App = new Ext.Application({
name: 'SmsthingyApp',
useLoadMask: true,
launch: function () {
Ext.data.ProxyMgr.registerType("contactstorage",
Ext.extend(Ext.data.Proxy, {
create: function(operation, callback, scope) {
},
read: function(operation, callback, scope) {
},
update: function(operation, callback, scope) {
},
destroy: function(operation, callback, scope) {
}
})
);
Ext.regModel("contact", {
fields: [
{name: "id", type: "int"},
{name: "givenName", type: "string"},
{name: "familyName", type: "string"},
{name: "emails", type: "auto"},
{name: "phoneNumbers", type: "auto"}
]
});
Ext.regStore('contacts',{
model: "contact",
proxy: {
type: "contactstorage",
read: function(operation, callback, scope) {
var thisProxy = this;
navigator.contacts.find(
['id', 'name', 'emails', 'phoneNumbers', 'addresses'],
function(deviceContacts) {
//loop over deviceContacts and create Contact model instances
var contacts = [];
for (var i = 0; i < deviceContacts.length; i++) {
var deviceContact = deviceContacts[ i ];
var contact = new thisProxy.model({
id: deviceContact.id,
givenName: deviceContact.name.givenName,
familyName: deviceContact.name.familyName,
emails: deviceContact.emails,
phoneNumbers: deviceContact.phoneNumbers
});
contact.deviceContact = deviceContact;
contacts.push(contact);
}
//return model instances in a result set
operation.resultSet = new Ext.data.ResultSet({
records: contacts,
total : contacts.length,
loaded : true
});
//announce success
operation.setSuccessful();
operation.setCompleted();
//finish with callback
if (typeof callback == "function") {
callback.call(scope || thisProxy, operation);
}
},
function (e) { console.log('Error fetching contacts'); },
{multiple: true}
);
}
}
});
Ext.regModel('Sms', {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'message', type: 'string' }
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title', message: 'Please select a contact for this sms.' }
]
});
Ext.regStore('SmsStore', {
model: 'Sms',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'sms-app-localstore'
},
getGroupString: function (record)
{
if (record && record.data.date)
{
return record.get('date').toDateString();
}
else
{
return '';
}
}
});
SmsthingyApp.views.ContactsList = new Ext.List({
id: 'ContactsList',
layout: 'fit',
store:'contacts',
itemTpl: '{givenName} {familyName}',
listeners: {'render': function (thisComponent)
{
SmsthingyApp.views.ContactsList.getStore().load();
}
},
onItemDisclosure: function (record) {
//Ext.dispatch({
// controller: SmsthingyApp.controllers.contacts,
// action: 'show',
// id: record.getId()
//});
}
});
SmsthingyApp.views.contactsListContainer = new Ext.Panel({
id: 'contactsListContainer',
layout: 'fit',
html: 'This is the sms list container',
items: [SmsthingyApp.views.ContactsList],
dockedItems: [{
xtype: 'toolbar',
title: 'Contacts'
}]
});
SmsthingyApp.views.smsEditorTopToolbar = new Ext.Toolbar({
title: 'Edit SMS',
items: [
{
text: 'Back',
ui: 'back',
handler: function () {
SmsthingyApp.views.viewport.setActiveItem('smsListContainer', { type: 'slide', direction: 'right' });
}
},
{ xtype: 'spacer' },
{
text: 'Save',
ui: 'action',
handler: function () {
var smsEditor = SmsthingyApp.views.smsEditor;
var currentSms = smsEditor.getRecord();
// Update the note with the values in the form fields.
smsEditor.updateRecord(currentSms);
var errors = currentSms.validate();
if (!errors.isValid())
{
currentSms.reject();
Ext.Msg.alert('Wait!', errors.getByField('title')[0].message, Ext.emptyFn);
return;
}
var smsList = SmsthingyApp.views.smsList;
var smsStore = smsList.getStore();
if (smsStore.findRecord('id', currentSms.data.id) === null)
{
smsStore.add(currentSms);
}
else
{
currentSms.setDirty();
}
smsStore.sync();
smsStore.sort([{ property: 'date', direction: 'DESC'}]);
smsList.refresh();
SmsthingyApp.views.viewport.setActiveItem('smsListContainer', { type: 'slide', direction: 'right' });
}
}
]
});
SmsthingyApp.views.smsEditorBottomToolbar = new Ext.Toolbar({
dock: 'bottom',
items: [
{ xtype: 'spacer' },
{
text: 'Send',
handler: function () {
// TODO: Send current sms.
}
}
]
});
SmsthingyApp.views.smsEditor = new Ext.form.FormPanel({
id: 'smsEditor',
items: [
{
xtype: 'textfield',
name: 'title',
label: 'To',
required: true
},
{
xtype: 'textareafield',
name: 'narrative',
label: 'Message'
}
],
dockedItems:[
SmsthingyApp.views.smsEditorTopToolbar,
SmsthingyApp.views.smsEditorBottomToolbar
]
});
SmsthingyApp.views.smsList = new Ext.List({
id: 'smsList',
store: 'SmsStore',
grouped: true,
emptyText: '<div style="margin: 5px;">No notes cached.</div>',
onItemDisclosure: function (record)
{
var selectedSms = record;
SmsthingyApp.views.smsEditor.load(selectedSms);
SmsthingyApp.views.viewport.setActiveItem('smsEditor', { type: 'slide', direction: 'left' });
},
itemTpl: '<div class="list-item-title">{title}</div>' +'<div class="list-item-narrative">{narrative}</div>',
listeners: {'render': function (thisComponent)
{
thisComponent.getStore().load();
}
}
});
SmsthingyApp.views.smsListToolbar = new Ext.Toolbar({
id: 'smsListToolbar',
title: 'Sent SMS',
layout: 'hbox',
items:[
{xtype:'spacer'},
{
id:'newSmsButton',
text:'New SMS',
ui:'action',
handler:function()
{
var now = new Date();
var smsId = now.getTime();
var sms = Ext.ModelMgr.create({ id: smsId, date: now, title: '', narrative: '' },'Sms');
SmsthingyApp.views.smsEditor.load(sms);
SmsthingyApp.views.viewport.setActiveItem('smsEditor', {type: 'slide', direction: 'left'});
}
}
]
});
SmsthingyApp.views.smsListContainer = new Ext.Panel({
id: 'smsListContainer',
layout: 'fit',
html: 'This is the sms list container',
dockedItems: [SmsthingyApp.views.smsListToolbar],
items: [SmsthingyApp.views.smsList]
});
SmsthingyApp.views.viewport = new Ext.Panel({
fullscreen: true,
layout: 'card',
cardAnimation: 'slide',
items:[
SmsthingyApp.views.contactsListContainer,
SmsthingyApp.views.smsListContainer,
SmsthingyApp.views.smsEditor
]
});
}
})
I'm using eclipse and LogCat tab keeps marking this red
02-08 11:11:58.741: E/Web Console(13886): Uncaught TypeError: Cannot read property 'contacts' of undefined at file:///android_asset/www/app.js:35
I'm guessing this has something to with why I can't see the contacts in the contactsListContainer.
Any help please?
I'm not a Sencha expert but I do know that this line:
var App = new Ext.Application({
will cause problems with PhoneGap as we also declare a variable called App. It would be better to change that line to be something like:
var myApp = new Ext.Application({
to avoid the name conflict.
If that doesn't resolve your problem I suggest you read over my post on searching contacts. I'd make sure I could successfully search for contacts before adding in Sencha.

Categories

Resources