This is my first attempt on Sencha Touch. So please excuse me if I am asking any silly questions.
I am trying to follow clean MVC pattern from Sencha. on Home page when user clicks I want to load AdboutView, I am not sure what is wrong in this code, but it doesn't fire "onGoToAboutMeCommand"
app.js
Ext.application({
name: "HaBoMobile",
models: ["HomeModel"],
stores: ["HomeStore"],
controllers:["HomeController"],
views: ["HomeView", "AboutView"],
launch: function () {
var homeLandingView = {
xtype: "LandingView"
};
var aboutView = {
xtype: "AboutView"
};
Ext.Viewport.add([homeLandingView, aboutView]);
}
});
HomeView.js
Ext.define("HaBoMobile.view.HomeView", {
extend: "Ext.navigation.View",
fullscreen:true,
requires: "Ext.form.FieldSet",
alias: "widget.LandingView",
config: {
//scrollable: 'vertical',
items: [
{
title: 'Harsha Bopuri',
padding: 10,
items: [
{
itemId: "aboutButton",
xtype: 'button',
text: 'About me',
handler: function () {
this.fireEvent("goToAboutMeCommand", this);
}
}
]
}
],
//Not sure when I have handler, if I still need listeners?
listeners: [
{
delegate: "#aboutButton",
event: "tap",
fn: "onAboutButtonTap"
}
]
},
onAboutButtonTap:function(){
this.fireEvent("goToAboutMeCommand", this);
},
onBackButtonTap: function () {
console.log("backToHomeCommand");
this.fireEvent("backToHomeCommand", this);
}
});
HomeController.js
Ext.define("HaBoMobile.controller.HomeController", {
extend: "Ext.app.Controller",
config: {
refs: {
homeView: "HomeView"
},
control: {
homeView: {
goToAboutMeCommand: "onGoToAboutMeCommand"
}
}
},
// Transitions
slideLeftTransition: { type: 'slide', direction: 'left' },
slideRightTransition: { type: 'slide', direction: 'right' },
// Commands.
onGoToAboutMeCommand: function () {
console.log("onBackToHomeCommand");
this.showAboutMe();
},
onBackToHomeCommand: function () {
console.log("onBackToHomeCommand");
this.shoHomePage();
},
showAboutMe: function () {
Ext.Viewport.animateActiveItem(this.getAboutView(), this.slideRightTransition);
},
shoHomePage: function () {
Ext.Viewport.animateActiveItem(this.getHomeView(), this.slideRightTransition);
},
// Base Class functions.
launch: function () {
this.callParent(arguments);
var homeStore = Ext.getStore("HomeStore");
homeStore.load();
console.log("launch");
},
init: function () {
this.callParent(arguments);
console.log("init");
}
});
I think the problem is in your refs section of your controller,refs takes key value pair.key can be any reference and while value is used in ComponentQuery.
I would suggest to add xtype in your HomeView.js file,like below.
Ext.define("HaBoMobile.view.HomeView", {
extend: "Ext.navigation.View",
xtype: 'HomeView',
//-----
Button handler that fires goToAboutMeCommand event runs in the scope of the button but in the controller you listen to homeView so the event is never caught.
This button handler should work:
handler: function (btn) {
var hv = btn.up('homeView');
hv.fireEvent("goToAboutMeCommand", hv);
}
Related
Why is the first listener not working and the other one working?
How to set the first listener to work?
Maybe the problem is related to scope, this?
How can I set this to see the function available in MainControllers?
It is modern version ExtJS 6.2
Structure folders:
//FeedViewer
//app
//view
//main
/MainController.js
/MainModel.js
/FeedForm.js
/Feeds.js
//classic
//modern
//src
//view
//main
/Main.js
MainController.js:
Ext.define('FeedViewer.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onNewFeed: function () {
alert('Hello');
}
});
Feeds.js:
Ext.define('FeedViewer.view.main.Feeds', {
extend: 'Ext.grid.Grid',
xtype: 'feedslist',
requires: [
'ContactsApp.view.feeds.MainController',
'ContactsApp.view.feeds.MainModel'
],
viewModel: 'feeds',
controller: 'feeds',
columns: [{
dataIndex: 'feed',
text: 'feed'
}],
items: [{
xtype: 'toolbar',
docked: 'left',
items: [{
xtype: 'button'
text: 'Add New Feed',
iconCls: 'fa fa-plus',
listeners: {
click: 'onNewFeed' * * //It doesn't work**
}
}]
}],
listeners: {
select: 'onNewFeed' * * //It works**
}
});
In modern toolkit Ext.Button click event is called tap. Also you can use handler config. Here's the FIDDLE
YUI3 custom view module do not calls showPanel() function
whn the user clicks to the Y.SpHeader (view) should call showPanel event handler.
the code Does not throw any error in console it simply do not work. and not logging in console that the button is clicked.
YUI.add('sp-header-section', function(Y){
Y.SpHeader = Y.Base.create('sp-header-section', Y.View, [], {
events: {
'#sign-up': {'click': "showPanel"}
},
initializer: function(config){
this._initPanel();
},
render: function(){
new Y.SpDropdownMenu({
contentBox: "#top_menu",
descriptions: true
}).render();
},
// Private Methods
_initPanel: function(){
var okButton = this.okBotton;
var cancelButton = this.cancelButton;
this.panel = new Y.Panel({
width: 300,
centered: true,
headerContent: 'Sign Up To Recieve a Book',
bodyContent: 'CAUTION: Watch out for random panels.',
zIndex: 999,
modal: true,
});
},
showPanel: function(){
Y.log('the button is clicked');
this.panel.reder();
},
// Panel Buttons Configurations
okButton: {
value: 'ok',
section: Y.WidgetStdMod.FOOTER,
action: function (ev) {
ev.preventDefault();
this.hide();
}
},
cancelButton: {
value: 'cancel',
section: Y.WidgetStdMod.FOOTER,
action: function (ev) {
ev.preventDefault();
this.hide();
}
}
}, {
ATTRS:{
}
});
},'1.0', {requires: ['sp-dropdown-menu', 'panel', 'escape', 'view']});
YUI().use('sp-header-section', function(Y){
var header = new Y.SpHeader({}).render();
});
I've just started working with Sencha Touch over the past couple days and I've run into a few questions. The main one is, when working with anything that doesn't regularly have user click interaction (titlebar, html text, etc for some random examples), is it possible to click on things like this and get a panel to appear.
I know that with buttons and other things, you have a tap, itemtap, etc, but I'm not sure about instances like this. Any help would be appreciated with examples.
Yes you can. Check out my blog post here: http://www.senchahackers.com/touch/multiple-tap-listeners-one-xtemplate/ that explains exactly how to do that.
Basically you can listen for a tap event on any element, as long as you add it to the list of 'delegates'
In your view:
listeners: {
tap: {
element: 'element',
delegate: '.app-box, .doc-box, .bubble-holder',
fn: function(e){
var url = e.target.name,
divClassName = e.delegatedTarget.className,
appbox = "app-box",
docbox = "doc-box",
bubble = "bubble-holder";
console.log(divClassName);
switch(divClassName){
case docbox :
//lets say you have an element '.doc-box' that you want to click and show the panel
// show the panel, which is a separate file, shown below
var profileController = YourApp.getController('YourController');
//call the showProfilePanelPopup() method in your controller, passing in this as the element that shows it
profileController.showProfilePanelPopup(this);
break;
case appbox :
alert(appbox);
break;
case bubble :
alert(bubble);
break;
}
}
}
}
Then in your controller:
extend: 'Ext.app.Controller',
config: {
refs: {
profilePanelPopup: {
autoCreate: true,
selector: '#profilePanelPopup',
xtype: 'profilePanelPopup'
}
}
},
showProfilePanelPopup: function(btn, action, values) {
var me = this;
var popup = me.getProfilePanelPopup();
popup.showBy(btn);
popup.on('hide', function () {
popup.destroy();
}, this);
}
Assuming you some Panel in your views directory like this:
Ext.define('App.view.ProfileNowPop', {
extend : 'Ext.Panel',
alias: 'widget.profileNowPop',
xtype: 'profilePanelPopup',
config: {
height: (Ext.os.deviceType != "Desktop") ? "35%" : 253,
cls:'profilePop',
left: '1%',
padding: 0,
top: '1%',
width: (Ext.os.deviceType != "Desktop") ? '40%' : '36%',
hideOnMaskTap: true,
modal: {
cls:'opaquemask'
},
scrollable: false,
store: 'ProfilePopStore',
model: 'App.model.ProfilePopModel',
items:[
{
xtype: 'fieldset',
items: [
{
xtype: 'textfield',
id: 'gradePopField0',
cls: 'gradePopField',
style: 'background: #f7f7f5',
listeners: {
initialize: function(ele, eOpts) {
this.setReadOnly(true);
}
}
}
]
}
]
},
initialize: function() {
this.callParent(arguments);
}
});
I defined a class 'IMS.SellMgt.testForm'.when i click the button 'submit',i want to get 'var test = this.formPanel;',why test is null? if i want to get this.formPanel,how can i do?Thank you!
Ext.define('IMS.SellMgt.testForm', {
formPanel: null,
LoadForm: function () {
this.formPanel = new Ext.form.Panel({
renderTo: 'form-ct',
frame: true,
title: 'XML Form',
width: 300,
items: [{
xtype: 'fieldset',
title: 'Contact Information',
defaultType: 'textfield',
items: [{
fieldLabel: 'First Name',
emptyText: 'First Name',
name: 'first'
}
]
}],
buttons: [{
text: 'Submit',
handler: function () {
var test = this.formPanel;
}
}]
});
}
});
Ext.onReady(function () {
var frmTest = Ext.create('IMS.SellMgt.testForm', {});
frmTest.LoadForm();
});
try something like:
......
handler: function () {
var test = this.findParentByType(Ext.form.FormPanel);
}
....
handler is a simpler way of specifying a click event listener for the button. Since it is short hand, it has some drawbacks.
With handler, the context of the function is always the button. In other words, this inside the handler function is the button, not your form.
In order for this to be your class, use a listener with a scope specified:
buttons: [{
text: 'Submit',
listeners: {
click: function() {
this.formPanel; // will work now
...
},
scope: this // this is the key
}
}]
You can also use up to find the form:
handler: function() {
var form = this.up('form');
...
}
I have following problem. I have grid with tbar. Inside tbar I have number of Ext.form.field.Trigger.
When the user click on trigger button I want to filter the store using function that is provided with grid. I want to define functionality of triggerclick inside defined class, so I can reuse this component with different grid.
So, in short I want to find the panel where clicked component is placed and call panel function, or pass reference of panel to triggerclick, or fire an event with some parameter that will calculated based on where the button was clicked, or maybe there is a better method to accomplish this.
The code (FilterField -> extension of trigger):
Ext.define('GSIP.core.components.FilterField', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.filterfield',
initComponent: function() {
this.addEvents('filterclick');
this.callParent(arguments);
},
onTriggerClick: function(e, t) {
//Ext.getCmp('gsip_plan_list').filterList(); - working but dont want this
//this.fireEvent('filterclick'); - controller cant see it,
//this.filterList; - is it possible to pass scope to panel or reference to panel
//e.getSomething() - is it possible to get panel via EventObject? smth like e.getEl().up(panel)
}
});
code of panel:
Ext.define('GSIP.view.plans.PlanReqList', {
extend: 'Ext.grid.Panel',
alias: 'widget.gsip_devplan_list',
id: 'gsip_plan_list',
title: i18n.getMsg('gsip.view.PlanReqList.title'),
layout: 'fit',
initComponent: function() {
this.store = 'DevPlan';
this.tbar = [{
xtype: 'filterfield',
id: 'filter_login',
triggerCls: 'icon-user',
//scope:this - how to pass scope to panel without defining onTriggerClick here
// onTriggerClick: function() {
// this.fireEvent('filterclick'); //working event is fired but controller cant see it
// this.filterList; //this is working but i dont want to put this code in every filterfield
// },
// listeners : {
// filterclick: function(btn, e, eOpts) { //this is working
// }
// },
}];
this.columns = [{
id: 'id',
header: "Id",
dataIndex: "id",
width: 50,
sortable: true,
filterable: true
}, {
header: "Name",
dataIndex: "name",
width: 150,
sortable: true,
filterable: true
}, {
header: "Author",
dataIndex: "author",
sortable: true,
renderer: this.renderLogin,
filterable: true
}];
this.callParent(arguments);
},
filterList: function() {
this.store.clearFilter();
this.store.filter({
property: 'id',
value: this.down("#filter_id").getValue()
}, {
property: 'name',
value: this.down("#filter_name").getValue()
});
},
renderLogin: function(value, metadata, record) {
return value.login;
}
});
part of code of Controller:
init: function() {
this.control({
'attachments': {
filesaved: this.scanSaved,
}
}, {
'scan': {
filesaved: this.attachmentSaved
}
}, {
'#filter_login': {
filterclick: this.filterStore //this is not listened
}
});
},
filterStore: function() {
console.log('filtering store');
this.getPlanListInstance().filter();
},
Controller can listen to anything. Just need to specify exactly what to. But I would fire events on the panel level - add this into your trigger handler:
this.up('panel').fireEvent('triggerclicked');