Hi i am trying to use javascript session storage on my app in sencha touch with model, after a long search on the internet i am not getting lucky at all, please help if you can, Thanks.
This is my code so far.
My Controller the onStorage function works, getStorage usession.load fails to load, thats were i'm stuck
Ext.define('SideMenu.controller.Menu', {
extend: 'Ext.app.Controller',
currView:'home',
requires: ['SideMenu.model.Mymdl'],
config: {
refs: {
btn_localstore:'#btn_localstore',
btn_getlocalstore:'#btn_getlocalstore'
}
control: {
btn_localstore:{
tap: 'onStorage'
},
btn_getlocalstore:{
tap: 'getStorage'
},
},
onStorage:function(){
//create model and store data
var myMod = Ext.create('SideMenu.model.Mymdl',{
brandName:'Nike Jordan',
brandCat:'Sneakers'
});
myMod.save({
success:function(res){
console.log('saved to model : '+res.get('brandName'));
}
});
},
getStorage:function(){
var usession = Ext.ModelMgr.getModel('SideMenu.model.Mymdl');
console.log('model is :'+usession);
usession.load(0, {
scope: this,
success: function(model, opp) {
console.log('passed '+model.get('brandCat'));
},
failure: function(record, operation) {
console.log('failed : '+operation);
// Ext.Viewport.setMasked(false);
//====================================================
// alert('could not get session details');
//====================================================
}
});
}
}
My Model
Ext.define('SideMenu.model.Mymdl', {
extend : 'Ext.data.Model',
xtype : 'Mymdl',
requires:['Ext.data.proxy.SessionStorage'],
id : 'Mymdl',
config: {
fields: [
'brandName',
'brandCat'
]
,
proxy : {
type: 'localstorage',
id : 'mymdl'
}
}
});
My app.js i excluded the other stuff dts not needed in this case
models: ['Mymdl'],
views: ['Main', 'Home'],
controllers: ['Menu'],
launch:function()
{
Ext.create('SideMenu.model.Mymdl');
}
Your answer would be appreciated, thanks
You will need to call the model load method using the id of the model data you want to retrieve from local storage.
You can get the id from the model save callback function
var modelId;
myMod.save({success:function(res){
modelId = res.getId();
console.log('saved to model : '+res.get('brandName'));
}
});
Then use this id when you load the model:
SideMenu.model.Mymdl.load(modelId, function(record) {
console.log('Brand: ' + record.get('brandName'));
}
You can set the id value directly when you save the model. This would save you from having to retrieve and save the auto-generated id on each save.
Related
I'm new to rally app SDK and trying to do the tutorials (from Youtube and from rally site)
when I'm trying to create an iterationComboBox the object is created but with no values ("There are no Iterations defined").
i tried to run both the video tutorial code from github (session_4_interactive_grid)
// Custom Rally App that displays Defects in a grid and filter by Iteration and/or Severity.
//
// Note: various console debugging messages intentionally kept in the code for learning purposes
Ext.define('CustomApp', {
extend: 'Rally.app.App', // The parent class manages the app 'lifecycle' and calls launch() when ready
componentCls: 'app', // CSS styles found in app.css
defectStore: undefined, // app level references to the store and grid for easy access in various methods
defectGrid: undefined,
// Entry Point to App
launch: function() {
console.log('our second app'); // see console api: https://developers.google.com/chrome-developer-tools/docs/console-api
this.pulldownContainer = Ext.create('Ext.container.Container', { // this container lets us control the layout of the pulldowns; they'll be added below
id: 'pulldown-container-id',
layout: {
type: 'hbox', // 'horizontal' layout
align: 'stretch'
}
});
this.add(this.pulldownContainer); // must add the pulldown container to the app to be part of the rendering lifecycle, even though it's empty at the moment
this._loadIterations();
},
// create iteration pulldown and load iterations
_loadIterations: function() {
this.iterComboBox = Ext.create('Rally.ui.combobox.IterationComboBox', {
fieldLabel: 'Iteration',
labelAlign: 'right',
width: 300,
listeners: {
ready: function(combobox) { // on ready: during initialization of the app, once Iterations are loaded, lets go get Defect Severities
this._loadSeverities();
},
select: function(combobox, records) { // on select: after the app has fully loaded, when the user 'select's an iteration, lets just relaod the data
this._loadData();
},
scope: this
}
});
this.pulldownContainer.add(this.iterComboBox); // add the iteration list to the pulldown container so it lays out horiz, not the app!
},
// create defect severity pulldown then load data
_loadSeverities: function() {
this.severityComboBox = Ext.create('Rally.ui.combobox.FieldValueComboBox', {
model: 'Defect',
field: 'Severity',
fieldLabel: 'Severity',
labelAlign: 'right',
listeners: {
ready: function(combobox) { // this is the last 'data' pulldown we're loading so both events go to just load the actual defect data
this._loadData();
},
select: function(combobox, records) {
this._loadData();
},
scope: this // <--- don't for get to pass the 'app' level scope into the combo box so the async event functions can call app-level func's!
}
});
this.pulldownContainer.add(this.severityComboBox); // add the severity list to the pulldown container so it lays out horiz, not the app!
},
// Get data from Rally
_loadData: function() {
var selectedIterRef = this.iterComboBox.getRecord().get('_ref'); // the _ref is unique, unlike the iteration name that can change; lets query on it instead!
var selectedSeverityValue = this.severityComboBox.getRecord().get('value'); // remember to console log the record to see the raw data and relize what you can pluck out
console.log('selected iter', selectedIterRef);
console.log('selected severity', selectedSeverityValue);
var myFilters = [ // in this format, these are AND'ed together; use Rally.data.wsapi.Filter to create programatic AND/OR constructs
{
property: 'Iteration',
operation: '=',
value: selectedIterRef
},
{
property: 'Severity',
operation: '=',
value: selectedSeverityValue
}
];
// if store exists, just load new data
if (this.defectStore) {
console.log('store exists');
this.defectStore.setFilter(myFilters);
this.defectStore.load();
// create store
} else {
console.log('creating store');
this.defectStore = Ext.create('Rally.data.wsapi.Store', { // create defectStore on the App (via this) so the code above can test for it's existence!
model: 'Defect',
autoLoad: true, // <----- Don't forget to set this to true! heh
filters: myFilters,
listeners: {
load: function(myStore, myData, success) {
console.log('got data!', myStore, myData);
if (!this.defectGrid) { // only create a grid if it does NOT already exist
this._createGrid(myStore); // if we did NOT pass scope:this below, this line would be incorrectly trying to call _createGrid() on the store which does not exist.
}
},
scope: this // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
},
fetch: ['FormattedID', 'Name', 'Severity', 'Iteration'] // Look in the WSAPI docs online to see all fields available!
});
}
},
// Create and Show a Grid of given defect
_createGrid: function(myDefectStore) {
this.defectGrid = Ext.create('Rally.ui.grid.Grid', {
store: myDefectStore,
columnCfgs: [ // Columns to display; must be the same names specified in the fetch: above in the wsapi data store
'FormattedID', 'Name', 'Severity', 'Iteration'
]
});
this.add(this.defectGrid); // add the grid Component to the app-level Container (by doing this.add, it uses the app container)
}
});
and the code from Rally site (https://help.rallydev.com/apps/2.0rc2/doc/#!/guide/first_app).
// Custom Rally App that displays Defects in a grid and filter by Iteration and/or Severity.
//
// Note: various console debugging messages intentionally kept in the code for learning purposes
Ext.define('CustomApp', {
extend: 'Rally.app.App', // The parent class manages the app 'lifecycle' and calls launch() when ready
componentCls: 'app', // CSS styles found in app.css
launch: function() {
this.iterationCombobox = this.add({
xtype: 'rallyiterationcombobox',
listeners: {
change: this._onIterationComboboxChanged,
ready: this._onIterationComboboxLoad,
scope: this
}
});
},
_onIterationComboboxLoad: function() {
var addNewConfig = {
xtype: 'rallyaddnew',
recordTypes: ['User Story', 'Defect'],
ignoredRequiredFields: ['Name', 'ScheduleState', 'Project'],
showAddWithDetails: false,
listeners: {
beforecreate: this._onBeforeCreate,
scope: this
}
};
this.addNew = this.add(addNewConfig);
var cardBoardConfig = {
xtype: 'rallycardboard',
types: ['Defect', 'User Story'],
attribute: 'ScheduleState',
storeConfig: {
filters: [this.iterationCombobox.getQueryFromSelected()]
}
};
this.cardBoard = this.add(cardBoardConfig);
},
_onBeforeCreate: function(addNewComponent, record) {
record.set('Iteration', this.iterationCombobox.getValue());
},
_onIterationComboboxChanged: function() {
var config = {
storeConfig: {
filters: [this.iterationCombobox.getQueryFromSelected()]
}
};
this.cardBoard.refresh(config);
}
});
both give me an empty iteration box.
i'm getting user stories data when running code from session 3 on the video,by creating a store of user stories. I googled it and searched here for duplicates but with no successso far, so what can be the issue?
Thanks!
I copied the code you posted, both apps, without making any changes, ran the apps and the iteration box was populated in both cases. It's not the code.
Maybe if you are getting "There are no Iterations defined" there are no iterations in your project?
The second code you posted which you copied from the example in the documentation has a bug in it and even though the iteration combobox is populated, the cards do not show on a board. DevTools console has error: "Cannot read property 'refresh' of undefined".
I have a working version of this app in this github repo.
I am trying to store data offline aspect, but here i want to store data on localstorage, did not store able to store this, all value getting null in localstorage.
This the based on ; http://www.robertkehoe.com/2012/11/sencha-touch-2-localstorage-example/
Models:
*Online.js*
Ext.define('default.model.Online', {
extend: 'Ext.data.Model',
config: {
fields: [
'cat_id',
'category_name'
]
}
});
Offline.js
Ext.define('default.model.Offline', {
extend: 'Ext.data.Model',
config: {
fields: [
'cat_id',
'category_name'
],
identifier:'uuid', // IMPORTANT, needed to avoid console warnings!
proxy: {
type: 'localstorage',
id : 'category'
}
}
});
Stores:
Ext.define('default.store.News', {
extend:'Ext.data.Store',
config:{
model:'default.model.Online',
proxy: {
timeout: 3000, // How long to wait before going into "Offline" mode, in milliseconds.
type: 'ajax',
url: 'http://alucio.com.np/trunk/dev/sillydic/admin/api/word/categories/SDSILLYTOKEN/650773253e7f157a93c53d47a866204dedc7c363?_dc=1376475408437&page=1&start=0&limit=25' , // Sample URL that simulates offline mode. Example.org does not allow cross-domain requests so this will always fail
reader: {
type: "json",
rootProperty: "data"
}
},
autoLoad: true
}
});
Controller:
Ext.define('default.controller.Core', {
extend : 'Ext.app.Controller',
config : {
refs : {
newsList : '#newsList'
}
},
init : function () {
var onlineStore = Ext.getStore('News'),
localStore = Ext.create('Ext.data.Store', {
model: "default.model.Offline"
}),
me = this;
localStore.load();
onlineStore.on('refresh', function (store,record) {
Ext.Msg.alert('Notice', 'You are in online mode', Ext.emptyFn);
// console.dir(record.data.name);
console.dir(record.get('category_name'));
console.log(record.items[0].raw.category_name);
console.log(record.get('category_name'));
// Get rid of old records, so store can be repopulated with latest details
localStore.getProxy().clear();
store.each(function(record) {
var rec = {
name : record.data.category_name+ ' (from localStorage)' // in a real app you would not update a real field like this!
};
localStore.add(rec);
localStore.sync();
});
});
onlineStore.getProxy().on('exception', function () {
me.getNewsList().setStore(localStore); //rebind the view to the local store
localStore.load(); // This causes the "loading" mask to disappear
Ext.Msg.alert('Notice', 'You are in offline mode', Ext.emptyFn); //alert the user that they are in offline mode
});
}
});
I think, I am not getting value from this record.data.category_nam . Here I am getting first value from this:record.items[0].raw.category_name. So how to store in localstorage.
and View file:
Ext.define('default.view.Main', {
extend : 'Ext.List',
config : {
id : 'newsList',
store : 'News',
disableSelection : false,
itemTpl : Ext.create('Ext.XTemplate',
'{category_name}'
),
items : {
docked : 'top',
xtype : 'titlebar',
title : 'News List'
}
}
});
In localstorage, following output:
category-5ea01a8d-ef1e-469e-8ec4-790ec7306aaf
{"cat_id":null,"category_name":null,"id":"5ea01a8d-ef1e-469e-8ec4-790ec7306aaf"}
category-f3e090dd-8f25-4b20-bb6e-b1a030e07900
{"cat_id":null,"category_name":null,"id":"f3e090dd-8f25-4b20-bb6e-b1a030e07900"}
category-5148e6eb-85ae-4acd-9dcd-517552cf5d97
{"cat_id":null,"category_name":null,"id":"5148e6eb-85ae-4acd-9dcd-517552cf5d97"}
category-ec23ff8b-1faa-4f62-9284-d1281707a9bc
{"cat_id":null,"category_name":null,"id":"ec23ff8b-1faa-4f62-9284-d1281707a9bc"}
category-6c1d
I have display in view but could not store in localstorage for offline propose.where i did wrong, i could not get it.
Record you created should match the SF.model.Offline model.
In your following code
var rec = {
// name is the field name of the `SF.model.Offline` model.
name : record.data.category_name+ ' (from localStorage)'
};
localStore.add(rec);
localStore.sync();
But you see there is no field called name in SF.model.Offline model.
This is how you should do
Models
Ext.define('SF.model.Online', {
extend : 'Ext.data.Model',
config: {
fields: ['cat_id','category_name'],
}
});
Ext.define('SF.model.Offline', {
extend : 'Ext.data.Model',
config: {
fields: ['cat_id','category_name'],
identifier:'uuid',
proxy: {
type: 'localstorage',
id : 'category'
}
}
});
Store
Ext.define('SF.store.Category', {
extend : 'Ext.data.Store',
config : {
model : 'SF.model.Online',
storeId : 'category',
proxy: {
timeout: 3000,
type: 'ajax',
url: 'same url' ,
reader: {
type: "json",
rootProperty: "data"
}
},
autoLoad : true
}
});
In Controller
var onlineStore = Ext.getStore('category'),
localStore = Ext.create('Ext.data.Store', {
model: "SF.model.Offline"
}),
me = this;
localStore.load();
onlineStore.on('refresh', function (store, records) {
localStore.getProxy().clear();
onlineStore.each(function(record) {
//You creating record here, The record fields should match SF.model.Offline model fields
var rec = {
cat_id : record.data.cat_id + ' (from localStorage)',
category_name : record.data.category_name + ' (from localStorage)'
};
localStore.add(rec);
localStore.sync();
});
});
onlineStore.getProxy().on('exception', function () {
me.getNewsList().setStore(localStore);
localStore.load();
Ext.Msg.alert('Notice', 'You are in offline mode', Ext.emptyFn);
});
I have couple of tree panels, each configured with individual tree stores. I have configured a proxy for one store. On load event of this, i am trying to load the second store(proxy memory) like below. But it doesn't work.
EXT js Version: 4.0.7
_treeStore2 = Ext.create('Ext.data.TreeStore', {
model: 'Scenario',
proxy : {
type : 'memory'
}
});
_treeStore1 = Ext.create('Ext.data.TreeStore', {
model: 'Scenario',
root:'data1',
proxy : {
type : 'ajax',
url: '/proj/examples?id='+_Id,
reader : {
type : 'json',
root:'data1'
}
},
listeners: {
'load': {
fn: function(store, records, success, operations) {
_treeStore2.setRootNode(_treeStore1.getProxy().getReader().jsonData.data2);
}
}
});
Sample JSON data:
{"data1":[{"name":"value","children":[]}],"data2":[{"name":"value","children":[]}]}
Try using loadData(data2) or loadRawData methods.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Store-method-loadRawData
I have a ProjectsController like:
Ext.define('SimpleTodo.controller.ProjectsController', {
extend: 'Ext.app.Controller',
refs: [
{ ref: 'addProjectPanel', selector: '#addProjectPanel' }
],
init: function() {
this.control({
'button[action=addProject]': {
click: this.addProject
}
});
},
addProject: function() {
var form = this.getAddProjectPanel().getForm();
if (form.isValid()) {
var projectsStore = Ext.data.StoreManager.lookup('projects'); // Am getting null here
projectsStore.add(form.getFieldValues());
projectsStore.sync();
} else {
Ext.Msg.alert('INVALID!');
}
}
});
I believe the problem is because the store has not been initialized yet? How then should I modify my code? My store is defined like:
Ext.define('SimpleTodo.store.Projects', {
extend: 'Ext.data.Store',
requires: [
'SimpleTodo.model.Project'
],
model: 'SimpleTodo.model.Project',
storeId: 'projects'
});
I encounted the same problem when trying to load my store, thus populating my Gridview/Table. I fixed it by moving the function to launch, wonder if thats the right way? In the docs, init is used
Ext.define('SimpleTodo.controller.SidebarController', {
extend: 'Ext.app.Controller',
...
launch: function() {
var projectsStore = Ext.data.StoreManager.lookup('projects');
projectsStore.load();
},
Add
stores:
[
'Projects'
],
to controller code and then you can use
getProjectsStore();
to refer to.
Have a look at http://docs.sencha.com/ext-js/4-0/#!/guide/mvc_pt3, 1. Getting References
Have u config a proxy to load the data?
Anyway place
models: [name of the model],
stores:[ name of the store],
into controller
Set into Store autoLoad:true;
Set a Proxy into Model to tell how load data into store.
Ref:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.proxy.Proxy
In the standard "Pull to Refresh" plugin, the list store gets updated. However, I have two lists and I need to update a different store for my detail list. How can I override the update event and reload my other store? I tried adding a simple listener but it's not firing.
[Update]
I got this snippet from the Sencha site to work:
plugins: [
{
xclass: 'Ext.plugin.PullRefresh',
pullRefreshText: 'Pull down for more new Events!',
refreshFn: function(plugin) {
console.log( "I'm pulled" );
}
}
]
Original code:
Ext.define('SenchaFiddle.view.ListView', {
extend: 'Ext.dataview.List',
xtype: 'main-list',
config: {
plugins: [
'pullrefresh',
{
pullRefreshText: 'Do it!',
type: 'listpaging',
// Don't offer "Load More" msg
autoPaging: false,
refreshFn: function() {
console.log("Boom");
},
listeners: {
'updatedata': function(plugin, list) {
console.log("Getting the data");
}
}
}
],
layout: 'fit',
width: 300,
itemTpl: '{text}'
}
});
In Sencha Touch 2.2, they have removed the refreshFn config from Ext.util.PullRefresh. I have successfully implemented a custom refreshFn with the new version of Sencha Touch by overriding the fetchLatest function inside Ext.util.PullRefresh like so...
Ext.define('MyApp.overrides.PullRefreshOverride', {
override: 'Ext.plugin.PullRefresh',
fetchLatest: function() {
var list = this.getList();
switch(list.getItemId()) {
case "list1":
this.updateStore1();
break;
case "list2":
this.updateStore2();
break;
}
this.callParent(arguments);
},
//My own custom function to add to the plugin
updateStore1: function() {
//Code to update store 1
},
//My own custom function to add to the plugin
updateStore2: function {
//Code to update store 2
}
});
Having a look at Ext.plugin.PullRefresh definition in sencha-touch-all-debug, I see this config:
/*
* #cfg {Function} refreshFn The function that will be called to refresh the list.
* If this is not defined, the store's load function will be called.
* The refresh function gets called with a reference to this plugin instance.
* #accessor
*/
refreshFn: null,
It might be a good idea that you can achieve what you need through refreshFn config.
For those who need the refreshFn back, there is a PullRefreshFn extension for PullRefresh.
I needed PullRefresh to get triggered by a Panel, rather than a List or Dataview and I also needed to manually load and set data to my Dataview upon user triggering the PullRefresh.
For this I needed the refreshFn config function that existed prior to Sencha 2.2, so here is my implementation.
PullRefreshFn (Modified)
Ext.define('Ext.plugin.PullRefreshFn', {
extend: 'Ext.plugin.PullRefresh',
alias: 'plugin.pullrefreshfn',
requires: ['Ext.DateExtras'],
config: {
/**
* #cfg {Function} refreshFn The function that will be called to refresh the list.
* If this is not defined, the store's load function will be called.
*/
refreshFn: null
},
fetchLatest: function() {
if (this.getRefreshFn()) {
this.getRefreshFn().call();
} else {
var store = this.getList().getStore(),
proxy = store.getProxy(),
operation;
operation = Ext.create('Ext.data.Operation', {
page: 1,
start: 0,
model: store.getModel(),
limit: store.getPageSize(),
action: 'read',
sorters: store.getSorters(),
filters: store.getRemoteFilter() ? store.getFilters() : []
});
proxy.read(operation, this.onLatestFetched, this);
}
}
});
My Controller
Ext.define('myApp.controller.MyController', {
extend: 'Ext.app.Controller',
requires: ['Ext.plugin.PullRefreshFn'],
...
// More code
...
// Binds the Pull Refresh to myPanel view item.
// myPanel is a panel. Not list nor dataview.
setPullRefresh: function () {
var me = this;
// We get reference to myPanel and
// we set PullRefreshFn
this.getMyPanel().setPlugins([{
xclass: 'Ext.plugin.PullRefreshFn',
docked: 'top',
// We set autoSnapBack to false,
// as we are going to trigger this manually
autoSnapBack: false,
// refreshFn will be called upon user releasing for refresh.
refreshFn: function() {
// This is a custom function that sets data to our dataview list.
// When it's done setting data, we trigger the snapBack.
me.populateMylist(function () {
me.getMyPanel().getPlugins()[0].snapBack(true);
});
}
}]);
}
});