Sencha Touch component.DataItem to dynamic list - extjs

Okay, so I have a view that extends Ext.dataview.component.DataItem' I have this function
onNameButtonTap: function(button, e) {
var record = this.getRecord();
console.log("The tid of this record is: " + record.get('tid'));
}
I am able to get an tid back from this tap, which I would like to use to load a new view that will use this id to alter the proxy url to get back different data. Here is the view:
Ext.define('AIN.view.Headlines.Card', {
extend: 'Ext.NavigationView',
xtype: 'headlineContainer',
config: {
tab: {
title: 'Headlines',
iconCls: 'star',
action: 'headlinesTab'
},
autoDestroy: false,
items: [
{
xtype: 'headlines',
store: 'Headlines',
}
]
}
});
How would I get the url parameter in my store to accept a URL like this one
'http://mywebsite.com/app-feeds/channels/' + tid
Thanks for reading, I am new to this and after hours of google searching I can't quite figure this out.
Update, this is working for me.
var store = Ext.StoreMgr.get('Headlines');
store: store.setProxy({
type: 'jsonp',
url: 'http://awebsite.com/app-feeds/channels/' + tid,
reader: {
type: 'json',
rootProperty: 'nodes',
record: 'node'
}
}).load()

You can set the URL of an Ext.data.Store by doing:
store.getProxy().setUrl('http://mywebsite.com/app-feeds/channels/' + tid);
Note that if you are planning on using this Store in multiple areas that use different URLs, you may want to create a new instance of it when you are setting the URL.

Related

Extjs 5 grid sync row render issues

using extjs 5.1.0
My issues, when I add value to store of grid and then call store.sync()
inserted row become selected (visually) but I cannot select it for edit or darg&drop row for sorting, only helps reload grid.
here is my store:
var store = Ext.create('Ext.data.ArrayStore', {
model: 'pbxe.module.conference.ConferenceModel',
proxy: {
type: 'direct',
api: {
read: pbxe._conference.read,
create: pbxe._conference.create,
update: pbxe._conference.update,
destroy: pbxe._conference.destroy,
},
reader: {
rootProperty: 'data',
totalProperty: 'totalCount',
successProperty: 'success',
messageProperty: 'message'
},
writer: {
writeAllFields: true,
},
},
autoSync: false,
autoLoad: true,
});
We ran into same problem, seems there is an issue of the Selection Model keeping a map of the records added to the store which can't get "deselected".
So with a bit of brute force:
// WORKAROUND for grid / selection model problem
// after adding multiple new records with Store.sync()
//var grid = grid bound to this store...
myStore.sync(
{
scope: this,
success: function (batch, options) {
var sm = grid.getSelectionModel();
var records = batch.operations[0].getRecords();
if (sm && sm.selected)
{ // deselect does not work as has bug leaves new records in map
sm.selected.map = {}; //wipe clear the selected records map
}
sm.select(records);
}
});
Hope this helps - works for us in Ext JS 5.1.0

extjs treestore with proxy type of rest appending -1 to model name

Having a peculiar problem with TreeStore where the rest type treestore adds -1 to name of model which breaks my backend routes.
TreeStore is defined as
Ext.define('Gateway.store.Company', {
extend: 'Ext.data.TreeStore',
model: 'Gateway.model.Company',
proxy: {
type: 'rest',
url: 'http://gateway-email-mock/',
reader: {
type: 'json'
}
}
});
where company model is defined as
Ext.define('Gateway.model.Company', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int' },
{name: 'name', type: 'string' }
]
});
The view interested in the store is
Ext.define('Gateway.view.company.Company', {
extend: 'Ext.tree.Panel',
alias: 'widget.company-list',
store: 'Gateway.store.Company',
rootVisible: false
});
When loading the widget the store creates URL
http://gateway-email-mock/Gateway.model.Company-1
How does -1 get there after the model name? I do not suppose this is intentional?
Thank you for any tips.
Rixo is correct, that is the tree store trying to load its root node. The default id generator generates its ID in the following way
idgen: {
isGenerator: true,
type: 'default',
generate: function () {
return null;
},
getRecId: function (rec) {
return rec.modelName + '-' + rec.internalId;
}
}
Which means your root record is rec.modelName + '-' + rec.internalId, which is exactly the request that is being made: http://gateway-email-mock/Gateway.model.Company-1
The solution is to make sure you create a root node with an ID, so that the tree's store will make a request for the correct ID , right it's generating the root node for you and giving it an automatic ID. See http://docs-origin.sencha.com/extjs/4.2.2/source/TreeStore.html#Ext-data-TreeStore-method-load and http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.data.TreeStore-cfg-root

Extjs4: How to share data between multiple stores or models?

I'm new to Ext and I'm struggling to figure out Models Stores and Proxies.
The server returns one large JSON object.
For example.
{
"responseHeader":{
"status":0,
"QTime":12,
"params":{
"facet":"true",
"facet.limit":"40"
}
},
"response":{
"numFound":3806,
"start":0,
"docs":[
{
//Lots of fields
"id":"1234",
...
//Some array properties
"testfield":[
"",
""
],
...
}
]
},
"facet_counts":{
"facet_queries":{
"email":3806
},
"facet_fields":{
"emailaddress":{
},
"subject":{
"candles":136,
"filter":130
},
"fromemail":{
},
//...
},
"facet_dates":{ },
"facet_ranges":{}
},
"highlighting":{
"some doc id":{
"emailtext":[ " Tel.: blah blah <em>blah</em>" ],
"combined":[ "<em>Email</em> To: blah blah blah" ]
}
}
}
I don't want to load this data more than once, I want to grab data from this object, for example the docs object, and put it into a grid. Then pull out another part to put into a selectbox.
How do I load this data once, yet create models and stores to give to grids and selectboxes, from it?
From what I read the proxy holds the servers response? So I tried creating a proxy out side of a store. Thinking I could use the same proxy with more than one store.
var myProxy1 = Ext.create('Ext.data.proxy.Proxy', {
type: 'ajax',
url : '../test',
reader: {
type: 'json',
root: 'responseHeader'
}
});
But when I pass myProxy1 to a store
Ext.define('Test', {
extend: 'Ext.data.Model',
fields: [
{name: 'status', type: 'int'},
{name: 'QTime', type: 'int'},
{name: 'param', type: 'auto'}
]
});
var myStore = Ext.create('Ext.data.Store', {
model: 'Test',
proxy: myProxy1,
autoLoad: true,
listeners:{
load: function( ths, records, successful, operation, eOpts ){
debugger;
}
}
});
It doesn't work. The load event is never fired. No data is loaded. I can see that the proxy made the request, I see the response from the server, but it doesn't load.
If I put the proxy inline it loads.
var myStore = Ext.create('Ext.data.Store', {
model: 'Test',
proxy:{
type: 'ajax',
url : '../test',
reader: {
type: 'json',
root: 'responseHeader'
}
},
autoLoad: true,
listeners:{
load:function( ths, records, successful, operation, eOpts ){
debugger;
}
}
});
I was thinking I could have one proxy, attach it to multiple stores, and just change the reader on it before I load the store.
You are pretty much there, and although I'm pretty sure you are understanding it all, for the benefit of others allow me to give an extended answer and a slightly modified solution to your problem.
Definitions:
The Model - primarily defines the fields a record has.
A Store - holds a collection of records.
A Proxy - facilitates server communication through a chosen method (Ajax, Direct, etc.) and maps CRUD (Create/Read/Update/Destroy) operations when such result from a change in the associated store or model.
A Reader - Tells a proxy how to interpret the data the server returns.
A Grid or Combobox - can display store records.
You scenario is not an uncommon one - while by default ExtJS loads each store separately, it is likely an application would prefer various stores to be loaded at once through a single read call; for example, when rendering one store-dependent component is dependent on another store.
Your code is not far off from achieving this, but here is how I do it. In effect, when a 'master' (Tasks) store loads, the server response also carries the data of a 'slave' (Tags) store, which is then manually loaded to that 'slave' store.
The 'slave' store (notice autoload: false and no read operation):
Ext.define('DL.store.Tags', {
extend: 'Ext.data.Store',
model: 'DL.model.Tag',
// Notice the tags are actually returned when the tasks are loaded and loaded into this store by the TasksStore.
autoLoad: false,
autoSync: true,
proxy: {
type: 'direct',
api: {
create: Tags.Create,
update: Tags.Update,
destroy: Tags.Destroy,
},
reader: {
type: 'json',
root: 'tags'
}
},
});
Then the 'master' store:
Ext.define('DL.store.Tasks', {
extend: 'Ext.data.TreeStore',
model: 'DL.model.Task',
autoLoad: true,
autoSync: true,
root: {
text: 'Root',
id: null,
expanded: true
},
proxy: {
type: 'direct',
api: {
create: Tasks.Create,
read: Tasks.Read,
update: Tasks.Update,
destroy: Tasks.Destroy,
},
},
onProxyLoad: function( aOperation )
{
// A read request for tasks will also return the user tags.
// So feed these tags into their store.
var iResult = aOperation.response.result,
iTagsStore = Ext.StoreManager.lookup( 'Tags' );
if ( Ext.isDefined( iResult.tags ) )
iTagsStore.loadRawData( iResult );
// We need this line for "Tasks" store to load its own data
this.callParent(arguments);
}
});
Basically all it does is it takes part of the server response and loads it manually to the 'slave' store.
The PHP server side code (for tasks read operation) involves:
return array(
'success' => true,
'children' => $iNodes,
'tags' => $iTags
);
Where children is the reader's root of the 'master' store, and tags is additional data that is then loaded into the 'slave' store.
I hope you can work how how to apply these concepts to your code.

Populating the value of a Label

I am using the MVC architecture (i have gone through the docs on MVC, but i am still lost here) and i need to know how to populate the records on to my Label. I know that i have to get this done by Stores.
I have loaded the values from the store, but unable to display it on my Panel for some reason. here's my code;
Most of the examples/books demonstrates how to display in a grid, but not a label (I know it has to be the same logic, but i am lost). And it shows how to write to a DB/JSON file and not display the values.
I need to display the COUNTRYNAME in the Label text. This is an example code that i am doing to understand this, can some one help me ?
Ext.define ('ProjectDisplayExample.model.Country',{
extend: 'Ext.data.Model',
//
fields:['countryid','countryname']
//
});
STORE
Ext.define('ProjectDisplayExample.store.Country',{
extend:'Ext.data.Store',
model:'ProjectDisplayExample.model.Country',
remoteGroup:true,
proxy: {
actionMethods : {
read : 'POST',
},
type: 'ajax',
url : '/server/country.php'
}
});
VIEW
Ext.define('ProjectDisplayExample.view.CountryWindow', {
extend: 'Ext.window.Window',
alias: 'widget.countrywindow',
...........
initComponent: function() {
var st = Ext.getStore('Country');
st.load();
this.items = [
{
items: [
{
xtype: 'panel',
region: 'north',
items: [{
xtype: 'label',
// NEED TO DISPLAY COUNTRT NAME FROM THE STORE HERE
}]
}]
}
UPDATE
var store = ... // Your store
store.on('load', function() {
// here store is loaded and you can do anything you want with it
console.log('store is loaded. number of records = ', store.getCount());
}, this, { single: true });
store.load; // I ADDED THIS LINE.................... <---------
UPDATE 2
this.items = [
{
items: [
{
xtype: 'panel',
region: 'north',
items: [{
xtype: 'label',
name : f
}]
}]
I will not post a code sample to exactly solve your question, but I will give you couple points:
Store contains array or records. So you can't just say give me country name from the store. You need first to get a record, for example: var r = store.getAt(0), and only after that you can get countyname field var f = r.get('countryname').
Load() method is asynchronous, so you can just execute it somewhere in the code and assume that for the very next line your store is ready. You need to subscribe to the load event, something like:
var store = ... // Your store
store.on('load', function() {
// here store is loaded and you can do anything you want with it
console.log('store is loaded. number of records = ', store.getCount());
}, this, { single: true });
store.load();
Labels as in xtype: label are actually very rarely used in ExtJs. What exactly are you trying to display in that panel? But anyhow... after you get data out of the store you can use something like update() or setValue() or any other method to update component.
Hope this helps...

ExtJS : How to set combobox id?

I have a little problem. At my application Im always building two linked combobox - country and towns(then country are selected - towns began to load). So i thinked - mbe write a constructor and minimized my code? Ok i did it. But i got a problem: i have 2-3 couple of this linked comboboxes on page and when i selected at second combo country, the data (towns) loads at first combo, because it has the same id. Ok - now im trying take a param id to constructor and it didnt work. How set id of combobox then i create an object?
Country combo
comboCountryClass = Ext.extend(Ext.form.ComboBox, {
fieldLabel: 'country',
anchor: '95%',
lazyRender:true,
store:new Ext.data.Store({
proxy: new Ext.data.HttpProxy(
{url: '../lib/getRFB.php?rfb_type=countrys',
method: 'GET'}
),
reader: countryReader,
autoLoad: true
}),
displayField:'country_name',
valueField:'country_id',
triggerAction:'all',
mode:'local',
listeners:{
select:{
fn:function(combo, value) {
var modelCmp = Ext.getCmp(this.town_name_id);
alert(this.town_name_id);
modelCmp.setValue('');
modelCmp.getStore().proxy.setUrl('../lib/getRFB.php');
modelCmp.store.reload({
params: { 'country_id': this.getValue(),rfb_type: 'towns' }
});
}
}
},
hiddenName:'country_id',
initComponent: function() {comboCountryClass.superclass.initComponent.call(this);}})
And town combo
comboTownClass = Ext.extend(Ext.form.ComboBox, {
fieldLabel:'town',
displayField:'town_name',
valueField:'town_id',
hiddenName:'town_id',
anchor: '95%',
id:this.town_name_id || 'youuuu',
store: new Ext.data.Store({
proxy: new Ext.data.HttpProxy(
{url: 'lib/handlers/orgHandler.php?action=read&towns=true',
method: 'GET'}
),
reader: townReader
}),
triggerAction:'all',
mode:'local',
initComponent: function() {comboTownClass.superclass.initComponent.call(this);}})
new comboTownClass({town_name_id:'townFormSearch'})
new comboCountryClass({town_name_id:'townFormSearch'})
You can set the id of the component by doing the following:
new comboTownClass({id:'townComboId'});
new comboCountryClass({id:'countryComboId'});
You can specify a default id, and when you pass an id in the config param it will overwrite the default value.
Although I agree with #Upper Stage you should try to limit the amount of hard-coded id values you have in the form - you can instead grab form elements using the form name instead.
I live by the rule: "never use hardcoded IDs." You can retrieve a unique ID from Ext JS using
Ext.id( null, 'someTextString' )
You will incur more bookkeeping when you use unique IDs, but you will not run into the problem about which you write above.
Sometimes I store unique IDs locally in an object and then reference that instance variable where necessary.
this.idForCombo = Ext.id( null, 'someTextString' );
var myCmp = new SomeConstructor({
id: this.idForCombo,
...more stuff });
myCombobox.id = yourId;

Resources