sencha -sdk /usr/local/bin/Sencha/touch-2.4.1 generate app -n $app_name -p $dir cd $dir sencha web -p 8282 start
script build nel contesto di una app cordova
cd $dir sencha app build build/android cd .. cp -r $dir/build/android www cordova build cordova run
cordova: sessione di esempio
sencha cordova init test0.SenchaTest2 SenchaTest2
sencha app build build/android
# mantenere commenti e indentazione sencha app build testing # senza 3 agomento, fa building production sencha app build
testting template
<!DOCTYPE HTML> <html manifest="" lang="en-US"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="../../../touch/resources/css/base.css"> <script type="text/javascript" src="../../../touch/sencha-touch-all-debug.js"></script> <script type="text/javascript"> // app def Ext.application({ name: 'Events', requires: [ /*...requires files*/ ], launch: function() { // Display the components Ext.create('Ext.Container', { fullscreen: true, items: [ /**/ ] }); } }); </script> </head> <body> </body> </html>
Ext.onReady(function() { var el = Ext.get('id');// works olso whith xtype, id, css selector, return ext dom wrapper var a_pars = Ext.select("p");// multiple elements var node = Ext.getDom('title');//return browser node });
// create a class, // dependencies will auto‐matically load through Ext.Loader() // $packagename maps to the app folder! app/$packagename/$ClassName.js Ext.define('$AppName.$packagename.$ClassName', { extend: 'Ext.Component', config: { html: 'Hello World' // getHtml() e setHtml() are automatically generated } constructor: function(config) { }, myVar: 1, myMethod: function(name){ //console.log("Log: " + name); } },function(){ // optional callback, after dependecy loaded }); Ext.create('DemoApp.view.DemoComponent', { fullscreen: true });
singleton:
Ext.define('Utils.common.Logger', { singleton: true, version: "1.02", log: function(msg) { console.log(msg); } });
static members:
Ext.define('App.utils.Commons', { statics: { YELP_API: 'http://test.com/search?', getUrl: function() { return this.YELP_API + "&q=" + 1; }, } });
multiple inheritance works (mixins)
Ext.define('App.vehicle.FourWheeler', { mixins: { canBrake: 'App.mixins.Brake', } }); var c = Ext.create('App.vehicle.FourWheeler'); c.mixinMethod();
showing components+containers:
var c = Ext.create('Ext.Component', { html: 'Hello World!' }); Ext.onReady(function() { Ext.require('Ext.Component'); Ext.create('Ext.Component', { html: 'Hello World!', style : { background: 'red' }, cls: 'box', width: 300, height: 100, renderTo: Ext.getBody() }); });
layout
Ext.define('App.view.MainInterface', { extend: 'Ext.Container', requires: ['Ext.layout.HBox'], layout: { type: 'hbox', // 'vbox', 'fit', 'card' align: 'start',// start (top), center (middle), end (bottom), and stretch pack: 'start' }, items: [{ xtype: 'component', html: 'box 1' },{ xtype: 'component', html: 'box 2' }] });
A card layout allows you to fit multiple components in one space, and show only one at a time
// stack is a Ext.Container stack.setActiveItem(2);
effects:
layout: { type: 'card', animation: { type: 'slide', direction: 'left' } }
in alternativa esiste, su tutti i componenti
docked: 'top'
templates:
Ext.create('Ext.Component', { tpl: Ext.create('Ext.XTemplate','<h1>{name}</h1><p>{description}</p>'), data: { name: 'Template', description: 'This is an example of how to configure a basic template.' } }); var c = Ext.create('Ext.Component', { tpl: '<h1>{name}</h1><p>{description}</p>', data: data, styleHtmlContent: true, cls: 'box', renderTo: Ext.getBody() }); // run time re-render c.setData(data); // definizione globale dei templates Ext.define('Utils.utils.Template', { statics: { MY_TPL: Ext.create('Ext.XTemplate','<h1>{name}</h1><p>{description}</p>'); } });
component selection with Ext.ComponentManager
// An alternative way of creating references to components is by using a refs object in the ==== // css selectors Ext.ComponentQuery.query('panel[title="Test"]'); Ext.ComponentQuery.query('#settingsview')[0].show(); Ext.ComponentQuery.query('#settingsview')[0].hide(); // a string with the xtype var cars = Ext.ComponentQuery.query('car'); // x id settato nel componente Ext.ComponentMgr.get(component_id) ;
define custom Component
Ext.define('BookTaxiBtn', { extend: 'Ext.Button', xtype: 'booktaxibtn', config: { text: 'Book a Taxi - listeners', margin: 5, listeners: { tap: 'bookTaxiEventHandler' }, }, bookTaxiEventHandler: function(b){ console.log('You tapped the ' + b.getText() + 'button'); } });
Event Listener
var callTaxiBtn3 = Ext.create('Ext.Button', { margin: 5, text: '3: Call a Taxi - on' }); callTaxiBtn3.on('tap', callTaxiEventHandler);
to debug the loader, use build debug custom code: if we add utils/ folder to the app, update the classpath in the hidden .sencha/sencha.cfg file so the App can be built:
app.classpath=${app.dir}/app.js,${app.dir}/app,${app.dir}/utils
sencha generate model $Model id:auto,name:string,price:float,
// creare un oggetto model var s = Ext.create('App.model.Setting', { city: "Amsterdam"}); var r = setting.validate();//trigger validation setting.set('country', 'NL');//setter
ref nel controller:
models:['$Model']
validation:
validations: [ { field:'fieldName', type: 'presence', message:'provide field' } ]
store:app/store/$store.js
Ext.define('App.store.$Store', { extend: 'Ext.data.Store', config: { model: 'App.model.Cab', autoLoad: true // will load its data automatically after creation } });
Stores can be written without models. You can write the model in- line in the store by just defining a fields array.
sono anche usati per filtrare i records
Ext.data.Store.filter(filters, [value], [anyMatch], [caseSensitive]);
incapsulate remote server connection
save your data model server side
Ext.define('SaveTest.model.Car', { extend: 'Ext.data.Model', config: { fields: [ { name: 'id', type: 'int' }, { name: 'brand', type:'string' }, ] }, App: { type: 'rest',// or ajax(will use POST insted of PUT/DELETE) format: 'php',//url extension, sometimes needed by services api: { create: 'cars/create', update: 'cars/update', read: 'cars/read', destroy: 'cars/delete' } } }); // test code car.save({ success: function() { console.log('The car record is saved'); }, failure: function(){ console.log('The car record could not be saved.'); } });
if you dont use a store, request the model via the ModelManager:
Ext.ModelManager.getModel('SaveTest.model.Car').load(1, { success: function(car){ console.log("record: " + car.getId()); }, failure: function(){ console.log("record could not be loaded"); } });
attenzione alle cross-domain restrictions @see jsonP
è possibile settare associazioni tra modelli
client proxies: data cache use LocalStorage on the model:
App: { type: 'localstorage', id: "Setting" }
Ext.define('App.model.Setting', { extend: 'Ext.data.Model', requires: ['Ext.data.identifier.Uuid'], config: { idProperty: 'id', identifier: 'uuid', fields: [ { name: 'id', type: 'auto' }, { name: 'gps', type: 'boolean' }, { name: 'city', type: 'string' }, { name: 'country', type: 'string' } ], validations: [{ type: 'presence', field: 'city', message: "Please provide a city." }, { type: 'presence', field: 'country', message: "Please provide a country." }], App: { type: 'localstorage', id: "Setting" } } });
salvataggio su sql DB:
xt.define('App.store.Cabs', { extend: 'Ext.data.Store', requires: [ 'Ext.data. App.JsonP', 'Ext.data. App.Sql' ], config: { model: 'App.model.Cab', autoLoad: false, sorters: [{ property: "name", direction: "ASC" }], grouper: { //group on the first character of Taxi name groupFn: function(record) { return record.get('name')[0].toUpperCase(); } }, //groupField: 'name', groupDir: 'DESC', filters: [{ //only display records that contain a phone number filterFn: function(item) { return item.get("phone").length > 0; } }], App: { type: 'sql', database: "__appname__", table: "Cabs" } } });
sencha generate controller $controller
Ext.define('App.controller.MyController', { extend: 'Ext.app.Controller', config: { models: ['$Model'], stores: ['$Store'], // ref to a component, equivalent to Ext.ComponentQuery.query('somextype'); // access with this.getRefMain() refs: { refMain: 'somextype' }, // event binding control: { 'somextype' : { initialize: 'onInitMain', tap: 'onTapMain', } }, onInitMain: function() { console.log("Initialize mainview"); }, onTapMain: function() { console.log("Tapped a button in mainview"); } }, launch: function(app) {}, // called when the application is launched init: function(){} // called during the application initialization });
Ext.Msg.alert('Title', 'The quick brown fox jumped over the lazy dog.', function(){ console.log(arguments); }); Ext.Msg.prompt('Welcome', 'Please enter your name', function(btn, val){ console.log(btn, val); }); Ext.Msg.confirm('Reload', 'Do you want to reload the page?', function(buttonId) { if (buttonId === 'yes') { window.location.reload(); } }); var myBox1 = Ext.Msg.show({ title: 'Address', message: 'Please enter your address:', width: 500, // Ext.MessageBox.OK (OK button with action UI skin) // Ext.MessageBox.YES (Yes button with action UI skin) // Ext.MessageBox.NO (No button) // Ext.MessageBox.CANCEL (Cancel button) // Ext.MessageBox.YESNOCANCEL (Cancel button, No button, and Yes button with action UI skin) // Ext.MessageBox.OKCANCEL (Cancel button, and OK button with action UI skin) // Ext.MessageBox.YESNO (No button, and Yes button with action UI skin) buttons: Ext.MessageBox.YESNOCANCEL, // Ext.MessageBox.ERROR (a round error sign) // Ext.MessageBox.INFO (a round info sign) // Ext.MessageBox.QUESTION (a question mark) // Ext.MessageBox.WARNING (a warning sign) iconCls: Ext.MessageBox.QUESTION, multiLine: true, prompt : { maxlength : 180, autocapitalize : true }, fn: function(buttonId) { alert('You pressed the "' + buttonId + '" button.'); } }); var myBox2 = Ext.Msg.show({ title: 'Ahoy!', message: 'Stop pirate, would ye like t\' proceed?', iconCls: Ext.MessageBox.ERROR, width: 200, buttons: [ {text: 'Aye', itemId: 'yes', ui: 'action'}, {text: 'Avast', itemId: 'no', ui: 'decline'} ], fn: function(buttonId) { alert('You pressed the "' + buttonId + '" button.'); } });
Ext.Viewport.setMasked({ xtype: 'loadmask', indicator: true, message: 'Fetching Data...' }); Ext.Viewport.unmask();
detail view:
Ext.define('App.view.DetailView', { extend: 'Ext.Container', xtype: 'detailview', requires: [ 'Ext.TitleBar', 'Ext.Button' ], config: { items: [ { xtype: 'titlebar', ui: 'light', docked: 'top', title: 'App', items: [{ iconCls: 'settings', ui: 'plain', align: 'right' }] } ], html: 'detail view' } });
list:
{ xtype: 'list', store: { fields: ['name'], data: [ {name: 'Leonardo'}, {name: 'Donatello'}, {name: 'Michelangelo'}, {name: 'Raphael'} ] }, itemTpl: '{name}', listeners: { refresh: function(list, index){}, select: function(list, index){}, deselect: function(list, index){ Ext.Msg.alert('Selected!', 'You selected ' + record.get('name')); } } }
var ref = Ext.Viewport.add({ xtype: 'panel', centered: true, modal: true });
any changes to the store are immediately reflected to the list on the screen
sencha generate form -name MyForm -fields field,field2:textfield
use Ext.form.Panel as container
validation: usare il model
var model = Ext.create("MyApp.model.MyModel"); myForm.updateRecord(model); var validationObj = model.validate(); if (!validationObj.isValid()) { validationObj.each(function(errorObj) { //loop through all errors } } else { //form is valid, now do something! myForm.submit(); }
POST data through an AJAX call:
Ext.Ajax.request({ url: 'data.php', jsonData : { city:"Amsterdam", country:"Netherlands" }, success: function(response) { myForm.reset(); }, failure: function(response) { Ext.Msg.alert('Oops',result.responseText);ΓÇ¿ } });
app.json file > css array > theme objectforce a style: ~http://localhost/app/?platform=ie10