ExtJS5 How to use ViewController and ViewModel without SenchaCmd - viewmodel

Question
I used to use extJs 4 with MVC, now I want to change to extjs 5 and add ViewModel and ViewController into it. But I have no privilege to install SenchaCmd to generate and compile the app as the guides says. I wonder if SenchaCmd is necessarily in ExtJs5, because when I add a ViewController for a view, there's error - Uncaught Error: [Ext.createByAlias] Unrecognized alias: controller.mainViewController.
If there's no SenchaCmd but I want to add ViewController and ViewModel for my app, what should I do?
Code
MyApp.view.main.MainView.js
Ext.define('MyApp.view.main.MainView', {
extend: 'Ext.tab.Panel',
alias: 'widget.MainView',
// requires: ['main.MainViewModel'],
controller: 'mainViewController',
// viewModel: {
// type: 'mainView'
// },
tabPosition: 'left',
tabRotation: 0,
defaults: {
textAlign: 'left',
bodyPadding: 15
},
items: [{
title: 'test',
items: [{
xtype: 'button',
listeners: {
onClick: 'onTest'
}
}]
}]
});
CaTools.view.main.MainViewController.js
Ext.define('CaTools.view.main.MainViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.mainViewController',
onTest: function() {
console.log('test -- ');
}
});
Error
Error - Uncaught Error: [Ext.createByAlias] Unrecognized alias: controller.mainViewController
Many Thanks!!

All that Sencha CMD is doing for you - in this context, anyway - is building a bootstrap file. As part of that, it knows that when it brings in a View, and it sees that the view has a viewModel and controller attribute, it looks for ViewModel and ViewController classes by convention (Model and Controller).
So you can do that yourself. Simply require the ViewModel and ViewController classes from within your View, just as you would require any other class.
(As an alternative - define the ViewModel and ViewController as additional classes inside the View's Javascript file; that way it's always loaded when the View is)

Related

Populating View in Sencha Touch 2

I'm trying to do is figure out how to pass in variables to a view from a controller.
For example, let's say I have a login screen where I want to display the application version and the some other custom device information. How would I go about passing that info into the view?
Ext.define('MyApp.view.Login', {
extend: 'Ext.form.Panel',
xtype: 'loginform',
config: {
items: [
{
xtype: 'label',
cls: 'appVersion',
html: 'Version #:' + versionNumber
}
]
}
});
Also how much different would it be if I used tpl instead of html ?
Thanks for any help!
You can always pass data during view creation like this:
var loginPanel = Ext.create('MyApp.view.Login', {
ver : versionNumber // any value or data you want to pass
});
for that you might have to define ver in your view's config
Ext.define('MyApp.view.Login', {
extend: 'Ext.form.Panel',
xtype: 'loginform',
config: {
ver : '', // Initialize with empty string
items: [
{
xtype: 'label',
cls: 'appVersion',
html: 'Version #:' + versionNumber
}
]
}
});
Once created with required value you can add it anywhere you want
Ext.Viewport.add(loginPanel);
You can always use PhoneGap (Cordova) for this: http://docs.phonegap.com/en/2.3.0/cordova_device_device.md.html#Device
Also, using html or tpl is fine.

Sencha Touch dynamically use of stores with mvc?

so here is the problem, I use MVC and I have several stores that I declared on app.js.
But now I need to do a login validation, and only load the stores after I get the response from the server, but if leave the declaration in app.js when the app loads it automatically loads all the stores.
Here is what my app is going needs to do:
LoginView make the validation, if validation is successful it changes the view to ListView, this view has a list that loads data from a store and this view can create other views with other lists.
I tried to require the stores in the ListView, but it throws errors cannot call method getCount of null.
What can I do to make it work. Thanks for the help.
Here is some code:
Ext.define("App.view.Listview", {
extend: 'Ext.Container',
xtype: 'listview',
requires: ['App.view.Listviewdetails',
'App.view.Filtros.FiltroJanelaPrincipal.Janelafiltrotiempoview',
'App.view.Menuview',
'App.view.Resultadopesquisaview',
'App.view.Pesquisaview',
'App.view.Maisinfousuarioview',
'Ext.Label',
'Ext.field.Search',
'App.store.Tiempos',
'App.store.Empresas',
'App.store.Produtos',
'App.store.Usuarios',
'App.store.FiltrosEvento',
'App.store.Historicos',
'App.store.Pesquisas'
],
config: {
id: 'listView',
layout: 'card',
items: {
layout: 'vbox',
id: 'listaEventos',
items: [
{
xtype: 'list',
id: 'listaTiempos',
flex: 6,
emptyText: 'Empty',
store: 'Tiempos',
itemTpl: '{dataTermino} {descricaoPrevia}'
}
]
}
and one of the stores:
Ext.define("App.store.Tiempos",{
extend: 'Ext.data.Store',
config: {
model: 'App.model.Tiempo',
autoLoad: true,
proxy: 'searchProxy'
}
});
You can add the stores in require in the respective view classes. It is not compulsory to add in app.js.
So after login when the view will be instantiated the store will be loaded automatically.

Extjs create dynamic accordion using store

I'm beginning development of an app in extjs. I'm using the MVC approach, as provided in the extjs documentation.
I have some dynamic data which needs to present the user with a set of accordion controls. I've got the data in a store, but I do not know how to dynamically create the accordion items (unlike grid panels, there doesn't appear to be a store data method).
Here is my current accordion view code - with static items:
Ext.define('BP.view.induction.LeftPage', {
extend: 'Ext.Panel',
alias : 'widget.leftpage',
title: "Left Page",
layout: {
type: 'accordion',
align: 'stretch'
},
layoutConfig: {
// layout-specific configs go here
titleCollapse: true,
animate: true,
activeOnTop: true
},
items: [{
xtype: 'panel', // fake hidden panel, so all appear collapsed
hidden: true,
collapsed: false
},{
xtype: 'panel',
title: 'Panel 1',
html: 'Panel content!'
},{
xtype: 'panel',
title: 'Panel 2',
html: 'Panel content!'
},{
xtype: 'panel',
title: 'Panel 3',
html: 'Panel content!'
}]
});
Any guidance on how to achieve the above would be appreciated, thank you.
[Edit] In response to sra's request, here is my controller:
Ext.define('BP.controller.Induction', {
extend: 'Ext.app.Controller',
views: [
'induction.Binder'
],
stores: [
'Sections',
'Categories',
'Tasks'
],
init: function() {
console.log('Initialized Induction!');
}
});
I should note here that this controller loads a parent view, which in turn loads the LeftPage view - I'm not sure if this creates any scoping issues. Furthermore, as you can see, more than one store is loaded.
You can do like this (untested example with some tweaks)
Ext.define('BP.view.induction.LeftPage', {
extend: 'Ext.Panel',
alias : 'widget.leftpage',
title: "Left Page",
layout: null,
layoutConfig: null,
store: null,
attentive: true,
initComponent: function() {
var me = this;
// begin edit
// only set the store if is is not already defined
me.store = me.store ? me.store : Ext.StoreMgr.lookup('Sections'); // you may change this to any storename you want
// end edit
me.layout = { // don't set objects directly in class definitions
type: 'accordion',
align: 'stretch'
};
me.layoutConfig = { // dont set objects directly in class definitions
titleCollapse: true,
animate: true,
activeOnTop: true
};
me.callParent(arguments);
if (me.attentive) {
me.store('load', me.onRebuildContent, me);
if (me.store.count() == 0)
me.store.load();
} else {
me.buildContent();
}
},
buildContent: function() {
var me = this;
function addItem(rec) {
me.add({
xtype: 'panel',
title: rec.get('titleProperty'),
html: rec.get('bodyProprty')
});
};
me.store.each(addItem);
},
onRebuildContent: function() {
var me = this;
me.removeAll();
me.buildContent();
}
});
Your store will need at least two properties; one for the title and one for the content. And the store need to be loaded before you should instantiate this. But that can easily be done within your controller.
Edit based on comment and new OP info:
Well your view is a bit out of control of the controller. So I recommend you to simply use the StoreManager to receive a valid instance (I've edited the code, I just didn'T know the correct store to use). The StoreManager will know about the store as long as you list him within a controller (StoreManager is capable of much more, but that is all you need to know at the moment). For a further release you could also use the mixin bindable which would manage a storebinding more clean and enables you to update your accordion after the store receives new data (get updated)
Edit for readability
I've just cleaned it up a bit and included a switch param attentive which would allow you to use this component as directly bound to a store, reacting on all load events or as a sort of static one where the store should already be loaded. All in all this should give you a start without making it to complex.

Sencha Touch 2.0 Controller refs attribute not working?

i am wondering about the 'refs' attribute of Sencha Touch class 'Ext.app.Controller'.
I saw a video tutorial where a simple contactForm was built. No i've tried to build a contact form for my app and i get an error: 'Uncaught TypeError: Object [object Object] has no method 'getContactForm''
Here's my controller
Ext.define('MyFirstApp.controller.Main', {
extend: 'Ext.app.Controller',
views: ['Viewport', 'Home'],
refs: [
{
ref: 'contactForm',
selector: '#contactForm'
}
],
init: function() {
this.control({
'button[action=submitContact]': {
tap: 'submitContactForm'
}
});
},
submitContactForm: function() {
var form = this.getContactForm();
form.submit({
url: 'contact.php'
});
}
});
I guess it's something wrong with the 'refs', in the video that guy said the "getContactForm" method will be created because of the "ref" attribute of "contactForm" but it doesn't. What am i doing wrong here?..Thanks for help!
The refs attribute property changed from Sencha Touch 2.0 developer preview version to beta/final version. So, what you wrote were correct for dev preview but presently it just name value pair. For your case:
refs: {
contactForm: '#contactForm'
}
I agree with jeremygerrits, I can't be sure that's the correct syntax for defining refs.
Based on the documentation, I would rather do it like this:
Ext.define('MyFirstApp.controller.Main', {
extend: 'Ext.app.Controller',
views: ['Viewport', 'Home'],
config: {
refs: {
contactForm: '#contactForm'
}
}
init: function() {
this.control({
'button[action=submitContact]': {
tap: 'submitContactForm'
}
});
},
submitContactForm: function() {
var form = this.getContactForm();
form.submit({
url: 'contact.php'
});
}
});
See also: http://docs.sencha.com/touch/2-0/#!/guide/controllers
It looks as though you may have the refs configured wrong. Here's a simple controller:
Ext.define('App.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
main: 'mainpanel'
}
}
});
mainpanel is an xtype or could be a css selector and main will give you getMain() like what was talked about in the video.

Disable docked button in a view from controller

I have a MVC app built with extJS 4.
I want to disable a docked button in a grid panel from a controller
Here is my grid panel view:
Ext.define('SDI.view.MissionsGridPanel', {
extend: 'Ext.grid.Panel',
alias: 'widget.missionsGridPanel',
width: 688,
title: 'Missions',
store: 'MissionsStore',
tbar:[
{
text:'Delete mission',,
icon: '/images/delete.png',
itemId: 'removeMissionButton',
disabled: true,
action :'delete'
}
]...
Here is my controller :
Ext.define('SDI.controller.MissionsController', {
extend: 'Ext.app.Controller',
views: ['SDI.view.MissionsGridPanel'],
refs: [
{
selector:'missionsGridPanel',
ref:'missionsGridPanel'
},
{
selector:'missionsGridPanel button[action=delete]',
ref:'missionsGridPanelToolbarDelButton'
}
],
init: function() {
this.control({
'missionsGridPanel': {
selectionchange: this.onMissionSelect
}
})
},
onMissionSelect: function(pTarget,pRecord,pOptions){
console.log("Mission is selected")
this.getMissionsGridPanelToolbarDelButton().setDisabled(false);
}
});
I don't understand why this doesn't work.
"Mission is selected" is logged but the button remains disabled.
Here is how to troubleshoot this -
Go to the Firebug console, type this:
Ext.ComponentQuery.query('missionsGridPanel button[action=delete]')
and see if anything is being returned. I would recommend installing Illuminations for Developers firebug plugin to further help you figure out whats what on your page.
I am not sure why it's not working, but it works fine if you call it by itemid:
selector: 'missionsGridPanel #removeMissionButton'

Resources