List Component: How to detect which item was selected? - javascript

I can access a list (as a container of items) in a controller but I do not know how to access list items properties.
How to create the correct ComponentQuery rule? I tried 'list > item' but it does not work.
Each item has it's title but I get 'undefined' as output in selectSection.
Ext.define( 'UGP.controller.BeginList',
{
extend: 'Ext.app.Controller',
config:
{
views: [ 'BeginList' ],
control:
{
'list':
{
select: 'selectSection'
}
}
},
selectSection: function()
{
Ext.Msg.alert( 'title=' + this.title );
}
}
);
The BeginList.js with the list component:
Ext.define( 'UGP.view.BeginList',
{
extend: 'Ext.List',
config:
{
fullscreen: true,
itemTpl: '{title}',
data:
[
{ title: 'Chapter 1', id: 0, action: "selectSection" },
{ title: 'Chapter 2', id: 1, action: "selectSection" },
{ title: 'Chapter 3', id: 2, action: "selectSection" },
{ title: 'Chapter 4', id: 3, action: "selectSection" }
]
}
}
);

You can see in the select event documentation that it passes arguments. So you can change the signature of your selectSection function to this :
selectSection: function (list, record) {
Ext.Msg.alert( 'title=' + record.get( 'title' ) );
}
You can also take a look at the itemTap event which usually the one used to detect tap events on a list item.
Hope this helps

Related

Sencha 6.5 (modern) how to dynamically change the items in a menu in a title bar?

Well considering a grid I create in my application:
{
xtype: 'ordergrid',
itemId: 'ordergrid',
titleBar: {
shadow: false,
items: [{
align: 'right',
xtype: 'button',
text: 'Update status',
stretchMenu: true,
menu: {
itemId: 'status_menu',
defaults: {
handler: 'updateStatus'
},
indented: false,
items: [{
text: 'test1',
value: 'test1'
}, {
text: 'test2',
value: 'test2'
}, {
text: 'test3',
value: 'test4'
}]
}
}]
},
With ordergrid being defined with:
extend: 'Ext.grid.Grid',
xtype: 'ordergrid',
I wish to modify the items of the menu dynamically. I've first tried doing this through a store:
menu: {
itemId: 'status_menu',
defaults: {
handler: 'updateStatus'
},
indented: false,
store: { type: 'status' }
Though this doesn't seem to work. Then I tried accessing this menu through a component query, during the init function of some controller:
Ext.define('BinkPortalFrontend.view.main.OrderController', {
extend: 'Ext.app.ViewController',
alias: 'controller.order',
init: function () {
console.log('..... initializing ......');
const menus = Ext.ComponentQuery.query('ordergrid #status_menu');
const menu = menus[0];
menu.setItems([{
text: 'some',
value: 'some'
}, {
text: 'new',
value: 'mew'
}]);
},
};
However this returns an error: "Cannot read property 'setItems' of undefined"
Debugging shows the obvious problem: it doesn't find any menu.
What's more, even a "catch all" query like
Ext.ComponentQuery.query('menu');
or
Ext.ComponentQuery.query('#status_menu');
Shows an empty array: so what's going on? (I most definitely see the menu from its initial load).
There is one reason your menu is not created. Menu will created whenever button will tap or whenever getMenu() method get called.
If you want to get your menu using Ext.ComponentQuery.query(), so for this you need to do use initialize event of button and forcefully create menu using getMenu() method like below :-
{
xtype: 'button',
text: 'Update status',
stretchMenu: true,
menu: {
itemId: 'status_menu',
indented: false,
items: [{
text: 'test1',
value: 'test1'
}, {
text: 'test2',
value: 'test2'
}, {
text: 'test3',
value: 'test4'
}]
},
listeners: {
initialize: function(btn) {
Ext.defer(function() {
// This will print undefined because menu have not created
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
//When we use getMenu method it will create menu item
btn.getMenu().hide();
// This will print menu component
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
}, 10)
}
}
}
Another way you can use getMenu() method of button. It will return the menu component.
In this FIDDLE, I have created a demo using grid, button and menu. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
var store = Ext.create('Ext.data.Store', {
fields: ['name', 'email', 'phone'],
data: [{
'name': 'Lisa',
"email": "lisa#simpsons.com",
"phone": "555-111-1224"
}, {
'name': 'Bart',
"email": "bart#simpsons.com",
"phone": "555-222-1234"
}, {
'name': 'Homer',
"email": "home#simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}]
});
Ext.create('Ext.grid.Grid', {
title: 'Change menu items dynamically',
titleBar: {
shadow: false,
items: [{
align: 'right',
xtype: 'button',
text: 'Update status',
stretchMenu: true,
itemId: 'statusbtn',
menu: {
itemId: 'status_menu',
defaults: {
// handler: 'updateStatus'
},
indented: false,
items: [{
text: 'test1',
value: 'test1'
}, {
text: 'test2',
value: 'test2'
}, {
text: 'test3',
value: 'test4'
}]
},
listeners: {
initialize: function (btn) {
Ext.defer(function () {
// This will undefined because menu has not been created
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
//When we use getMenu method it will create menu item
btn.getMenu().hide();
// This will menu component
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
}, 10)
}
}
}, {
xtype: 'button',
align: 'right',
text: 'Change Items',
handler: function (btn) {
var newItems = [];
store.each(rec => {
newItems.push({
text: rec.get('name'),
value: rec.get('name')
})
});
/*
* You can also get menu using button
* btn.up('titlebar').down('#statusbtn').getMenu().setItems(newItems);
*/
Ext.ComponentQuery.query('#status_menu')[0].setItems(newItems);
Ext.toast('Menu items has been change. Please check', 2000);
}
}]
},
store: store,
columns: [{
text: 'Name',
dataIndex: 'name',
width: 200
}, {
text: 'Email',
dataIndex: 'email',
width: 250
}, {
text: 'Phone',
dataIndex: 'phone',
width: 120
}],
height: 200,
layout: 'fit',
fullscreen: true
});
}
});
For more details about component you can also see this ComponentManager

Problems with Sencha Touch variable access

I'm quite new to using Sencha Touch. I'm creating an app that has a sidebar and a map pane and when the user clicks on the Show Map button in the sidebar area the map is supposed to center on that location. Where I'm having an issue is that I'm unsure of how to access the {lat} and {lon} properties that are in the tpl variable from the handler function. My apologies if this is a trivial question, but it has me stumped.
Ext.define('Admin.view.Details',
{
extend: 'Ext.Panel',
xtype: 'details',
config:
{
styleHtmlContent: true,
scrollable: 'vertical',
title: 'Individual',
tpl:
[
'Account Number: {comid}',
'<br />',
'Address: ',
'{address} <br />',
'{lat},{lon}',
],
items:
[
{
title: 'Utilities',
items:
[
{
xtype: 'selectfield',
label: 'Utility Type',
options:
[
{text: 'Electricity', value: 'U1'},
{text: 'Water', value: 'U2'},
{text: 'Gas', value: 'u3' },
],
id: 'utilityType',
},
{
xtype: 'selectfield',
label: 'Coverage Area',
options:
[
{text: 'Subdivision', value: 'a1'},
{text: 'Zipcode', value: 'a2'},
{text: 'County', value: 'a3' },
],
id: 'areaType',
},
{
xtype: 'button',
text: 'Show Map',
ui: 'round',
padding:3,
margin:10,
id: 'mapsBTN',
handler: function() {
olMap.setCenter(new OpenLayers.LonLat(lon, lat).transform
(
new OpenLayers.Projection("EPSG:4326"),
olMap.getProjectionObject()
), 16);
}
},
]
},
]
}
});
You need to either implement de handler in your view's controller by adding references to your view and your button and then add a listener for the itemtap event of the button OR implement it in the constructor method of the view :
Ext.define('Admin.view.Details',{
extend: 'Ext.Panel',
xtype: 'details',
config:{
...
},
constructor: function() {
this.callParent(arguments);
var me = this;
this.child('#mapsBTN').setHandler(function() {
me.getTpl(); // Here's your tpl config object
});
}
});
Hope this helped
You can get any variable inside config object by getter.
this.getTpl(); //returns tpl variable
Also note that this must point out to your Admin.view.Details view.

ExtJS: store loaded, records in form but not in fields

I'm struggling with my application right in the beginning.
this.getScoresStore().on('load', function(score, records) {
var view = Ext.getCmp('scoreView');
view.down('form').loadRecord(records[0].data);
console.log(view.down('form').getRecord());
console.log(view.down('form').getValues());
});
After the store is loaded, I add the records to the form. Console says it's added, however the fields keep beeing empty.
Object { playerOne="301", playerTwo="301" }
Object { playerOne="", playerTwo="" }
Anyone got Ideas what could be wrong?
Controller:
Ext.define('Darts.controller.Scores', {
extend: 'Ext.app.Controller',
views: [
'score.View',
'score.Hit'
],
stores: [
'Scores'
],
models: [
'Score'
],
init: function() {
this.getScoresStore().on('load', function(score, records) {
var view = Ext.getCmp('scoreView');
view.down('form').loadRecord(records[0].data);
console.log(view.down('form').getRecord());
console.log(view.down('form').getValues());
});
this.control({
'scoreView' : {
afterrender: this.formRendered
}
});
},
formRendered: function(obj) {
console.log(obj.down('form').getRecord());
console.log('form rendered');
}
});
Views:
Ext.define('Darts.view.score.Hit' ,{
extend: 'Ext.panel.Panel',
alias : 'widget.scoreHit',
title : 'Hits',
score : 'Scores',
initComponent: function() {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name : 'playerTwo',
fieldLabel: 'Player 1'
}
]
}
];
this.callParent(arguments);
}
});
Ext.define('Darts.view.score.View' ,{
extend: 'Ext.panel.Panel',
alias : 'widget.scoreView',
id : 'scoreView',
title : 'Player Scores',
score : 'Scores',
initComponent: function() {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'numberfield',
name : 'playerOne',
fieldLabel: 'Player 1'
}, {
xtype: 'textfield',
name : 'playerTwo',
fieldLabel: 'Player 2'
}
]
}
];
this.buttons = [
{
text: 'Start Game',
action: 'start'
}
];
this.callParent(arguments);
}
});
Store
Ext.define('Darts.store.Scores', {
extend: 'Ext.data.Store',
model : 'Darts.model.Score',
autoLoad: true,
proxy: {
type: 'ajax',
api: {
read: 'data/scores.json',
update: 'data/updateScores.json'
},
reader: {
type: 'json',
root: 'scores',
successProperty: 'success'
}
}
});
Model:
Ext.define('Darts.model.Score', {
extend: 'Ext.data.Model',
fields: ['playerOne', 'playerTwo']
});
Data:
{
success: true,
scores: [
{id: 1, playerOne: '301', playerTwo: '301'}
]
}
I've tried numberfields, textfields as well as changing the data fom with ' to without ' and mixed.... nothing seems to help me.
The fields are rendered before store is loaded (test output still in the code)
I'm really out of ideas here and I've seen many topics, but none fits to my problem or fixes my problem. The form fields always keeps beeing empty.
I think your issue is that you need to pass a Model record into loadRecord method not the underlying data. So try changing line 3 to
view.down('form').loadRecord(records[0]);
As a side note, it's a bit odd to load the entire store just to get at a single record.
You might want to explore Model.load( id, {callback config} ) way of loading exact record that you need.

Toolbar in extjs4

I have some toolbar in my exts 4 window
this.tbar = {
xtype: 'toolbar',
items: [
{
id: "btnClearFilter",
itemId: "btnClearFilter",
action: 'delFilter',
disabled: true,
handler: function (btn, e) {
btn.setDisabled(true);
}
},
'-',
{
text: 'Export',
tooltip: 'Export',
disabled: false,
menu : {
items: [{
text: 'Export 1'
, icon: 'Content/Resources/images/Excel-16.png'
, action: 'export'
}]
}
}
]
};
From controller i can cause action delFilter like this
'ns-main-win > toolbar button[action=delFilter]': {
click: this.delFilter
},
How couse action from menu item?
I dunno what you mean, you want to trigger the action on delFilter?
Ext.getCmp('btnClearFilter').click()
Have you tried giving the menu item an id and then searching using that
'#export'{
click:this.export
}

Trouble with Sencha Touch MVC

I'm trying to learn how to use Sencha Touch to build web apps. I've been following the tutorial Here and I am a bit stuck. Below have created one controller, two views and a model (All other code is copy & paste from the tutorial). The first view, Index works great. However if I try to access the second, it brings up a blank page, none of the toolbar buttons work and it doesn't fire the alert.
If I do comment out the line this.application.viewport.setActiveItem(this.editGyms);, the alert will fire, but obviously, it doesn't render the page.
I've looked at a couple other tutorials, and they seem to also be using the setActiveItem member to switch views.. Am I missing something, or do I have to somehow deactivate the first view to activate the second or something?
HomeController.js
Ext.regController('Home', {
//Index
index: function()
{
if ( ! this.indexView)
{
this.indexView = this.render({
xtype: 'HomeIndex',
});
}
this.application.viewport.setActiveItem(this.indexView);
},
editGyms: function()
{
if ( ! this.editGyms)
{
this.editGyms = this.render({
xtype: 'EditGymStore',
});
}
this.application.viewport.setActiveItem(this.editGyms);
Ext.Msg.alert('Test', "Edit's index action was called!");
},
});
views/home/HomeIndexView.js
App.views.wodList = new Ext.List({
id: 'WODList',
store: 'WODStore',
disableSelection: true,
fullscreen: true,
itemTpl: '<div class="list-item-title"><b>{title}</b></div>' + '<div class="list-item-narrative">{wod}</div>'
});
App.views.HomeIndex = Ext.extend(Ext.Panel, {
items: [App.views.wodList]
});
Ext.reg('HomeIndex', App.views.HomeIndex);
views/home/EditGymStore.js
App.views.EditGymStore = Ext.extend(Ext.Panel, {
html: 'Edit Gyms Displayed Here',
});
Ext.reg('EditGymStore', App.views.EditGymStore);
models/appModel.js
Ext.regModel('WOD', {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'wod', type: 'string' },
{ name: 'url', type: 'string' }
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title' }
]
});
Ext.regStore('WODStore', {
model: 'WOD',
sorters: [{
property: 'id',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'wod-app-localstore'
},
// REMOVE AFTER TESTING!!
data: [
{ id: 1, date: new Date(), title: '110806 - Title1', wod: '<br/><br/>Desc1</br><br/>' },
{ id: 1, date: new Date(), title: '110806 - Title1', wod: '<br/><br/>Desc2</br><br/>' }
]
});
viewport.js with toolbar
App.views.viewport = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
cardSwitchAnimation: 'slide',
scroll: 'vertical',
styleHtmlContent: true,
style: 'background: #d8e2ef',
dockedItems: [
{
xtype: 'toolbar',
title: 'The Daily WOD',
buttonAlign: 'right',
items: [
{
id: 'loginButton',
text: 'Login',
ui: 'action',
handler: function() {
Ext.Msg.alert('Login', "This will allow you to Login!");
}
},
{
xtype: 'spacer'
},
{
xtype: 'button',
iconMask: true,
iconCls: 'refresh',
ui: 'action',
handler: function() {
Ext.Msg.alert('Refresh', "Refresh!");
}
}]
},
],
});
Thanks for the help!!
In HomeController.js your action function (editGyms) is the same name as the variable you're using for your view (this.editGyms) so when it tries to setActiveItem(this.editGyms) its actually passing the controllers action function rather than the results of this.render({...})
Either change the name of the controller action or change the name of the variable you use to hold the view.. like
editGyms: function() {
if ( ! this.editGymView) {
this.editGymView = this.render({
xtype: 'EditGymStore',
});
}
this.application.viewport.setActiveItem(this.editGymView);
Ext.Msg.alert('Test', "Edit's index action was called!");
}
I am colleagues with the guy that wrote the tutorial you are referring to. You should add a comment on that post because I described your problem to him and he said that he knows the solution.
You can just add a link to this page so that you won't need to describe everything again.
Also he will (very) soon publish the 3rd part of that tutorial that will cover some similar things.

Categories

Resources