Sencha Touch: Accessing the controls in view and calling their functions via their refrences in controller - sencha-touch

[Sencha Touch 2.4.0]
I have a problem where .setHtml and .setValue function called against the refrences of labels and textfields are not doing anything ie the change is not showcasing in UI as desired but after the line of code is executed If I run .getHtml or .getValue in the console of the browser the change is visible in the output of the console but nothing changes in the UI.
My scenario in this Test Application is I have 3 labels [lbl1,lbl2 and lbl3] and 3 textfields [txt1,txt2 and txt3] I access the lbl1,lbl3,txt1,txt3 via their refrences in the controller. I desire to change the content of the lbl1 and txt1 if user clicks the button in the same panel. I have another form [initial view] with only button. what It does is opens the panel with 3 labels, 3 textfields and a button as I have described above but before pushing this Panel I want to set lbl3 and txt3. In all the cases .setValue and .setHtml is not updating the UI. Can anyone help me what am I doing wrong in here? I have also attached the sencha architecture project in zip.
MainViewr (initial view)
Ext.define('MyApp.view.mainView', {
extend: 'Ext.navigation.View',
requires: [
'Ext.form.Panel',
'Ext.Button'
],
config: {
itemId: 'mynavigationview',
items: [
{
xtype: 'formpanel',
items: [
{
xtype: 'button',
itemId: 'mybutton1',
text: 'MyButton1'
}
]
}
]
}
});
2nd Panel
Ext.define('MyApp.view.MyFormPanel1', {
extend: 'Ext.form.Panel',
alias: 'widget.myformpanel1',
requires: [
'Ext.Panel',
'Ext.Button',
'Ext.field.Text',
'Ext.Label'
],
config: {
itemId: 'myformpanel1',
scrollable: true,
items: [
{
xtype: 'panel',
docked: 'top',
height: '100%',
scrollable: true,
items: [
{
xtype: 'button',
itemId: 'mybutton',
text: 'MyButton'
},
{
xtype: 'textfield',
itemId: 'txt3',
label: 'Field'
},
{
xtype: 'textfield',
id: 'txt2',
itemId: 'txt2',
label: 'Field',
name: 'txt2'
},
{
xtype: 'textfield',
itemId: 'txt1',
label: 'Field'
},
{
xtype: 'label',
html: 'Name 3',
itemId: 'lbl3'
},
{
xtype: 'label',
html: 'Name 2',
id: 'lbl2',
itemId: 'lbl2'
},
{
xtype: 'label',
html: 'Name1',
itemId: 'lbl1'
}
]
}
]
}
});
Controller for the 1st View. Here I want to change the content of the label and textfield (lbl3 and txt3 which is on the 2nd view via thier refs) but setValue and setHtml or even calling other functions against their refs like hide() or setHidden(true) does not show on the UI but if I do getValue(), getHtml, getHidden in the browser's console thier hidden property and content is changed but it is not reflected on UI.
Ext.define('MyApp.controller.MyController', {
extend: 'Ext.app.Controller',
config: {
refs: {
mainView: 'navigationview#mynavigationview',
lbl3: 'label#lbl3',
txt3: 'textfield#txt3',
myFormPanel1: 'formpanel#myformpanel1'
},
control: {
"button#mybutton1": {
tap: 'btnlogin_click'
}
}
},
btnlogin_click: function(button, e, eOpts) {
var myformpanel1 = Ext.create('widget.myformpanel1');
lbl3 = this.getLbl3();
txt3=this.getTxt3();
mainView = this.getMainView();
txt3.setValue('Hello');
lbl3.setHtml('Hello');
mainView.push({
xtype: "myformpanel1",
title: "Dashboard"
});
}
});
Controller for 2nd View. As you can see I have tried to change the content of lbl1,lbl2,txt1 and txt2 in the button click but the content of only lbl2 and txt2 are changing because I have accessed them via their ID and not via reference.
Ext.define('MyApp.controller.MyController1', {
extend: 'Ext.app.Controller',
config: {
refs: {
lbl1: 'label#lbl1',
txt1: 'textfield#txt1'
},
control: {
"button#mybutton": {
tap: 'setText_Click'
}
}
},
setText_Click: function(button, e, eOpts) {
lbl1 = this.getLbl1();
txt1 = this.getTxt1();
Ext.getCmp('txt2').setValue("Hello");
Ext.getCmp('lbl2').setHtml("Hello");
txt1.setValue("Hello");
lbl1.setHtml("Hello");
}
});
Is accessing controls via their IDs is the only way? because I have read somewhere that accessing the controls via ID is not very good thing to do in Sencha Touch. What am I doing wrong in here so that my code changes the content and properties of the controls internally but not reflected on UI as desired.

I checked your code and found out that this problem is causing because of the navigation view. I don't know the reason for this weird problem but changing the navigation view to Container solved the problem.
Main View :-
Ext.define('MyApp.view.MainView', {
extend: 'Ext.Container',
xtype: 'main',
requires: [
'Ext.form.Panel',
'Ext.Button'
],
config: {
itemId: 'mynavigationview',
items: [
{
xtype: 'button',
itemId: 'mybutton1',
text: 'MyButton1'
}
]
}
});
Set the form view on btnlogin_click like this:-
Ext.Viewport.setActiveItem(myformpanel1);

Related

How to place a button inside an input field using Sencha Touch?

When I try to put a container as a component in the textfield (according to Button inside of an input field Sencha Touch 2.0) my app crashes. The code below is for you to get an idea of the context, im didnt double check the syntax in the post but when I comment out the last item it works fine . I think it is the xtype: 'container' that generates the error (the error is "undefined function"). What am I doing wrong here? Im so bad at this...
Ext.define('myapp.view.AddAdvertView', {
extend: 'Ext.form.Panel',
xtype: 'addadvertview',
requires: [
'Ext.form.FieldSet',
'Ext.field.Text',
'Ext.field.Number',
'Ext.Button',
'Ext.field.Toggle',
'Ext.Container'
],
config: {
title: 'AddAdvertView',
items: [
{
name: 'heading',
xtype: 'textfield',
label: 'Heading',
border: 10,
margin:'0 0 1 0',
},
{
xtype: 'textfield',
component: {
xtype: 'container',
layout: 'hbox',
items: [
{
xtype: 'textfield',
flex: 3,
},
{
xtype: 'button',
flex: 1,
text: 'test'
}
]
},
})
You are right. The problem is the container inside the textfield.
When a textfield is generated and initialized it will set its original value. Since you have changed the component to container and it's not input anymore you get the problem. The initialization process calls the getValue methode of the component. Unfortunately container does not have one and that's rises the exception.
The solution to this problem is quite easy: create your custom textfield and override its getValue method.
Ext.define("MyApp.field.ButtonField", {
extend: "Ext.field.Text",
xtype: "buttonfield",
config: {
label: 'Textfield',
component: {
xtype: 'container',
layout: 'hbox',
items: [
{
xtype: 'textfield',
flex: 3,
},
{
xtype: 'button',
flex: 1,
text: 'test'
}
]
}
},
getValue: function () {
this.getComponent().down('textfield').getValue();
},
setLabel: function ( label ) {
this.getComponent().down('textfield').setLabel( label );
}
});
Since it has an xtype you can use it as follows:
Ext.define('MyApp.view.AddAdvertView', {
extend: 'Ext.form.Panel',
xtype: 'addadvertview',
requires: [
'Ext.form.FieldSet',
'Ext.field.Text',
'Ext.field.Number',
'Ext.Button',
'Ext.field.Toggle',
'Ext.Container',
'MyApp.field.ButtonField'
],
config: {
title: 'AddAdvertView',
items: [
{
name: 'heading',
xtype: 'textfield',
label: 'Heading',
border: 10,
margin:'0 0 1 0',
},
{
xtype: 'buttonfield',
label: 'blub'
}
]
}
});
You have to override some more methods (e.g. setValue) if you want to use the buttonfield like a normal field. So you delegate all textfield method calls to the wrapped textfield. But that should be easy now.

Sencha Touch 2 painted event not firing

I built a view and I want to do some manipulation of the elements, after the view has been painted.
I am trying to use the "painted" event with no avail.
Any ideas why?
Ext.define('TestApp.view.phone.RegisterViewPhone', {
extend: 'Ext.Panel',
xtype: 'RegisterViewPhone',
config: {
items: [
{
xtype: 'Header'
},{
xtype: 'panel',
itemId: 'thePanel',
html: 'THIS WILL HOLD THE VIEWS CONTENT'
},{
xtype: 'Footer'
}
],
listeners: [
{
delegate: '#thePanel',
event: 'painted',
fn: 'onPainted'
}
]
},
onPainted: function () {
alert('hey!');
}
});
You can attach listeners to that particular element like
{
xtype: 'panel',
itemId: 'thePanel',
html: 'THIS WILL HOLD THE VIEWS CONTENT',
listeners: {
painted: function(){
alert('hey!');
}
}
}
As painted is not dependent on individual element and it acts on page scope also U can write it in views directly
items: [
],
listeners: {
painted: function () {
alert('hey!');
}

Controller ref not working

In my SenchaTouch 2.3.1 app I have build a login panel for the user. It looks like this:
Ext.define('MyApp.view.LoginPanel', {
extend: 'Ext.form.Panel',
alias: 'widget.loginPanel',
requires: [
'Ext.form.FieldSet',
'Ext.field.Password',
'Ext.Button'
],
config: {
layout: 'vbox',
items: [
{
xtype: 'fieldset',
title: 'Business Login',
itemId: 'login',
items: [
{
xtype: 'emailfield',
itemId: 'email',
label: 'E-Mail',
name: 'email',
required: true
},
{
xtype: 'passwordfield',
itemId: 'password',
label: 'Passwort',
name: 'password',
required: true
}
]
},
{
xtype: 'button',
itemId: 'loginButton',
cls: 'button-blue',
text: 'Login'
},
{
xtype: 'panel',
itemId: 'loggedInPanel',
cls: 'logged-in-panel',
tpl: [
'Sie sind eingeloggt als {firstname} {lastname} (ID: {agentId})'
],
hidden: true,
margin: '10 0'
}
]
}
});
In my controller, I want to use a reference to this panel like this:
config: {
refs: {
loginPanel: 'loginPanel',
navigationView: '#morenavigation',
loggedInPanel: '#loggedInPanel',
loginButton: '#loginButton'
}
}
In the launch function of the controller, I want to check if the user already logged in to show his id and show a logout button. But when I try to get the panel ref, it's undefined. But why?
launch: function() {
var me = this,
sessionInfo = Ext.getStore('SessionInfo');
console.log(me.getLoginPanel()); <-- undefined
if (null !== sessionInfo.getAt(0).get('sessionId')) {
me.successfullLogin(sessionInfo.getAt(0).get('sessionId'));
}
}
Is anything actually creating an instance of your view?
Inside your application's launch method, you'll probably have to create an instance of it, and then either give your view the fullscreen: true config, or add it to the viewport. The examples on the Sencha Touch API docs for Ext.app.Application have the main view being created from the application's launch function.
The correct way of using the ref in my example would be:
refs: {
loginPanel: {
autoCreate: true,
forceCreate: true,
xtype: 'loginPanel'
}
}

Rendering a List in a Panel

I have a Panel where I render a search-form. This works.
My problem is rendering a List under that search-form (so in the same Panel).
This is what I've done so far:
Ext.define("TCM.view.UserSearch",
{
extend: "Ext.form.Panel",
requires:
[
"Ext.form.FieldSet",
"Ext.List"
],
xtype: "usersearch",
config:
{
scrollable:'vertical'
},
initialize: function ()
{
this.callParent(arguments);
var clubsStore = Ext.create('TCM.store.Clubs');
clubsStore.load();
var usersStore = Ext.create('TCM.store.Users');
var searchButton =
{
xtype: 'button',
ui: 'action',
text: 'Search',
handler: this.onSearchButtonTap,
scope: this
};
var topToolbar =
{
xtype: 'toolbar',
docked: 'top',
title: 'Search',
items: [
{ xtype: 'spacer' },
searchButton
]
};
var userClub =
{
xtype: 'selectfield',
store: clubsStore,
name: 'clubId',
label: 'Club',
displayField : 'name',
valueField : 'id',
required: true
};
var userList =
{
xtype: 'list',
store: usersStore,
itemTpl: '{name}',
title: 'Search results'
};
this.add([
topToolbar,
{
xtype: "fieldset",
items: [userClub]
},
userList
]);
},
onSearchButtonTap: function ()
{
console.log("searchUserCommand");
this.fireEvent("searchUserCommand", this);
}
});
I can't see anything being rendered under the fieldset (the searchform). What could be wrong?
Most of time, when you don't see a component it's because you did not set a layout to your container or a height.
You can find more about layout here.
In your case, you want to have two components in your container. Therefore, I suggest a Vbox layout.
Here's an example
Hope this helps.
I actually used something like this in a project try this...Put this in the items property of your fieldset...
{
xtype: 'searchfield',
clearIcon: true,
placeHolder: 'Type Some text'
},
{
xtype: 'list',
hidden:true, //Initially hidden populate as user types something
height: '150px',
pressedDelay: 1,
loadingText: '',
store: 'listStore',
itemTpl: '{\'What you want to be displayed as per your model field\'}'
}
In your controller write a handler for the keyup event of the searchfield to load the store with relevant data and toggle the hidden property of the list. Hopefully list should appear with the search results(Worked for me and looked quite good). Hope this helps...

Listener to Tab Item Click in Sencha

In my application, I'm using a tab panel with 5 items in it. Each item holds around 6 panels added in card layout. When I'm at the last panel inside a tab item, I need to get back to the initial panel by clicking on the bottom tab panel (somewhat similar to a normal tab view controller in iOS). I have came across some solutions I found here, but it seems to work only when I switch between the tabs. In fact I want to listen to the click event on the same tab icon. How can I do this?
I have worked on your problem. I think this is exactly what you want. Hope this helps. If not so, please leave a comment.
1). View (MyTabPanel1.js)
Ext.define('MyApp.view.MyTabPanel1', {
extend: 'Ext.tab.Panel',
config: {
scrollable: 'vertical',
items:
[
{
xtype: 'panel',
id:'cardpanel1',
title: 'Tab1',
layout: 'card',
items: [
{
html: "First Item",
items:
[
{
xtype: 'button',
text: 'Forward',
handler: function() {
Ext.getCmp('cardpanel1').setActiveItem(1);
console.log('Going to Second Item');
}
}
]
},
{
html: "Second Item",
items:
[
{
xtype: 'button',
ui: 'confirm',
text: 'Go back',
handler: function() {
Ext.getCmp('cardpanel1').setActiveItem(0);
console.log('Going to First Item');
}
}
]
}
]
},
{
xtype: 'panel',
title: 'Tab2',
scrollable: true,
items: [
{
xtype: 'button',
margin: 10,
ui: 'action',
text: 'Tab2'
}
]
},
{
xtype: 'panel',
title: 'Tab3',
scrollable: true,
items: [
{
xtype: 'button',
margin: 10,
ui: 'action',
text: 'Tab3'
}
]
}
]
}
});
2). Controller (MainController.js)
Ext.define('MyApp.controller.MainController', {
extend: 'Ext.app.Controller',
config: {
control: {
"tabpanel #ext-tab-1":{ //ext-tab-1 is the id for the 1st tab generated by Sencha
tap: 'ontap'
}
}
},
ontap: function (){
console.log('inside controller');
Ext.getCmp('cardpanel1').setActiveItem(0);
}
});
I would give a much simpler solution
This is my view called Viewport which is a TabPanel:
Ext.define('Sencha.view.iphone.Viewport',{
extend: 'Ext.TabPanel',
xtype: 'newviewport',
alias: 'widget.newTabPanel',
Now in my controller file:
Ext.define('Sencha.controller.iphone.main', {
extend: 'Ext.app.Controller',
config:
{
refs: {
theMainTabPanelTabbarTab: 'newTabPanel > tabbar > tab', //this the tab of the tabpanel, if we listen to it that way we will know of tab panel tap.
},
control: {
theMainTabPanelTabbarTab:{
tap: 'onTapMainTabPanel'
}
}
This is a working code and works fine. Hopefully this will help you.