Can any one tell me that how can we achieve the re usability concept in ExtJS 4? I have a page where I have 4 bar chart and for that I had to write same code 4 times. How to make it generic so that we can call one function which will take different parameters and that one function will create a chart depending on what inputs I had provided to the function.
Is there any example for that?
There's a whole bunch of information about writing classes. Look at any of the MVC examples.
A custom class:
Ext.define('MyClass', {
extend: 'Ext.Component',
initComponent: function(){
this.html += 'Foo';
this.callParent();
}
});
Ext.onReady(function(){
new MyClass({
renderTo: document.body,
html: 'X'
});
});
Related
I've been thinking about this problem for a while, and I can't seem to come up with a reasonable solution. What I would like to do is create getters/setters for a textfield/its value in my view. I realize that the preferred Ext JS way is using a reference within the controller and getting it that way, but that doesn't feel very object-oriented to me. I'd also have to wrap these getters and setters because I want to output a message if the getter returns undefined. What I'd like to do is create my own getters/setters or somehow override the default getters/setters. Here are some ways I was thinking of accomplishing this.
I was thinking I could use the config {}, but that appears to only work for variables I want to define. I then was thinking of using an id somehow, but the community seems split on whether that's a good practice or not. Which leads to my current solution... wrapping. Here's my code:
LoginWindow
Ext.define('MyApp.view.LoginWindow', {
extend: 'Ext.window.Window',
alias: 'widget.loginWindow',
autoShow: true,
closable: false,
border: 0,
plain: true,
allowBlank: false,
title: "Enter your username",
modal: true,
config: {
buttons: [{
text: "Ok"
}],
items: [{
xtype: 'textfield',
fieldLabel: 'Username',
id: 'loginUserInput',
name: 'loginUserInput',
msgTarget: 'under',
validator: function(value) {
if (Ext.isEmpty(value)) {
return "You need to enter a username.";
}
return true;
}
}]
},
constructor: function(config) {
this.callParent(config);
},
getButton: function() {
console.log('here');
}
});
MyController
Ext.define('MyApp.controller.Chat', {
extend: 'Ext.app.Controller',
requires: [
'Views.ChatModule.view.LoginWindow'
],
refs: [{
ref: 'loginWindow',
selector: 'loginWindow',
xtype: 'loginWindow',
autoCreate: true
}, {
ref: 'loginUserInput',
selector: '#loginUserInput'
}],
init: function() {
// The events controller oversees
this.control({
'loginWindow button[text="Ok"]': {
'click': this.onSubmitLoginWindow
}
});
},
getLoginUserInputValue: function() {
var loginUserInput = this.getLoginUserInput();
if (loginUserInput) {
var username = loginUserInput.getValue();
if (username) {
console.log(username);
} else {
console.warn("username is undefined");
}
}
console.warn("loginUserInput is undefined");
},
onSubmitLoginWindow: function(button, event, eOpts) {
this.getLoginUserInputValue();
}
});
This works, and I realize it's a very nit-picky thing, but it just doesn't feel right to have the getter in the controller. I feel like it'd be more object-oriented if it was in the Window. However, if I put it in the Window, I believe my only option is to lean on ids or manually create the textfield in the Window's initComponent--which would involve saving off a reference of the textfield in there, but that seems a bit inefficient... as I would have to make a call to doLayout as well.
Just to reiterate, I'd love to have the getters/setters in the Window, and I'm looking for a quick way to reference it, similar to how the controller references objects. I believe the main answer will be to use ids and making a call to Ext.ComponentQuery.query('#loginUserInput') in the Window, but I'd like to know if there were any better approaches out there... like overriding the auto generated getters/setters or adding a simple getter/setter for an input's value.
Cross-post from the Sencha forums.
Edit
I guess I was a bit unclear with what I want. As a more general statement, instead of jamming all things related to my view in the controller, I'd like to store it all in the view itself, which includes things like getters/setters. One of these getters/setters just so happens to be the loginUserInput getter.
Using a model is an interesting idea, but I feel like that would be a whole lot of overhead for singleton values. I'm basically looking for something like Java's setters/getters in the LoginWindow view... and hopefully something as simple as (or close to) Java's.
The idea of including (encapsulating) it in the view makes the controller a bit cleaner, and if I delete the view, I'm deleting its functions as well, so I don't have to go hunting for the functions in the controller... all I have to worry about is removing the references (which should be minimal).
I think that the "OO" way that you're looking is to work with a Ext.data.Model for your form. If you look at the Ext.form.Basic you have methods to manipulate a model (called record) and also get the object with the values of your view. So you need:
When you create your form, use loadRecord() to bind your form to a Model.
At any time you need, use getValues() to retrieve the values of your form fields.
When submiting your form, use getRecord() and getValues() to sync your record.
Ext.define('MyApp.model.Login',{
fields : [{
name: 'username',
type: 'string'
},{
name: 'password',
type: 'string'
}]
});
Ext.define('MyApp.controller.Login',{
...
refs : [{
selector: 'window form',
ref: 'formPanel'
}],
...
openForm : function() {
//load your form and then bind the new record
var formPanel = this.getFormPanel(), //Ext.form.Panel
form = formPanel.getForm(); //Ext.form.Basic
form.loadRecord(Ext.create('MyApp.model.Login'));
},
save : function() {
//get the values in the view
var form = this.getFormPanel().getForm(),
vals = form.getValues(),
record = form.getRecord();
console.log(vals); //see the object representation of your view here
record.set(vals); //update your model
//do whatever you need with your model
}
...
});
This is an good example when you need to save the form data. In the login I think you can work directly with getValues() without binding it to a Ext.data.Model.
I am not quite certain what problem you are trying to solve to be honest with you.
If you do not like controllers listening to buttons within your window, you can have button handlers witin your view definition fire custom events that controllers can listen on. Use fireEvent method. And by the way initConfig is a recommended way to setup your views. You can break it up into methods if you wish, 'this' reference is available and is the View component being instantiated.
If you need to find inner components within the View there are many methods available from up /down to nextSibling and query .
For Components:
• Ext.getCmp(id)
• Ext.ComponentQuery.query()
• up()
• down()
• nextSibling()
• previousSibling()
• child()
• previousNode()
plus various find.. Methods
EDIT
I think I understood what you mean by getter and setters. Ext forms have the fields finders to make it easy to get and set data to individual fields. See these SO questions: Best way to access adjacent components / fields and EXT.JS getting a list of items from a fieldset
Also like Sergio said there is getRecord getValues and setRecord methods on the form to deal with data binding. Thats it.
EDIT2
The best starting point guide that shows clear and claen MVC patterns as well as form handling. http://docs.sencha.com/extjs/4.1.3/#!/guide/application_architecture
My thoughts are something like this:
...
items: [],
constructor: function(config) {
this.loginUserInput = Ext.create('Ext.form.field.Text', {
fieldLabel: 'Username',
id: 'loginUserInput',
name: 'loginUserInput',
msgTarget: 'under',
validator: function(value) {
if (Ext.isEmpty(value)) {
return "You need to enter a username.";
}
return true;
}
});
this.items.push(this.loginUserInput);
this.callParent(config);
},
getLoginUserInput: function() {
var loginUserInput = this.loginUserInput;
if (!loginUserInput) {
console.warn("LoginWindow::getLoginUserInput: loginUserInput is undefined");
}
return loginUserInput;
}
So instead of letting Ext do its magic, I am now instantiating the object on my own, which then allows me to store away a reference of it, so I can easily access it in my getter. I just wonder if this is creating any sort of performance hit. It doesn't seem like it'd be that much worse... it actually seems like it'd be a bit better because I'm not referencing this object by its ID, and I don't have to go searching for it when I need it.
Previous attempt at this app was done in jqtouch and this effect worked perfectly. Im having a really hard time wrapping my head on how best to do this with sencha touch.
My situation is best described in this image
This is just one item that should populate a carousel so reusing it with different data is paramount (no hard coded html).
thank you
Finally solved it thought I should update it here
Ext.define('mobuy.view.myCarousel', {
extend: 'Ext.carousel.Carousel',
alias: 'widget.myCarousel',
config: {
myitems: 0,
},
updateMyItems: function(newItem) {
var localCarouselItems = [];
Ext.each(newItems, function(item){
localCarouselItems.push({
xtype:'localItem',
data:item.data
});
});
this.setItems(localCarouselItems);
this.setActiveItem(0);
}
})
what this does is basically create an array of new items of type localItem from the store when one calls setMyItems and sets the data (to be used with xtemplate or whatever) for each of those items.
If anybody needs more details please ask and I'll update my answer.
The code below is part of my controller function;
success: function (response) {
var text = response.responseText;
var result = Ext.decode(response.responseText);
var indexPanel = Ext.create('app.view.PersonDetails');
Ext.getCmp('mainView').push({
xtype:'person',
data: result
});
}
The code below, is the view, which i am passing values from my Controller function (above).
The code below, demonstrates hard coded data in that view (Hard coded text), but what i want to do is to display the data: result that i am passing from Controller function (above) to be displayed in the following view. How can i do this ?
Ext.define('app.view.UserInformation',{
extend:'Ext.Panel',
xtype:'person',
config: {
title:'Person details',
html:['Hard coded text'].join("")
}
});
UPDATE
The result contains several values like;
result.name, result.age. result.gender
I will be passing result to the other view.
1.) from the View, how can i add a button ? and wen the user clicks on that button how can i fetch the result.age field and do a if condition to check if the age is below 10 ?
2.) Imagine, if there's a field called, result.imageurl, how could i display the image on the other view (in a frame) ?
UPDATE2
Ext.getCmp('mainpanel').push({
title: 'Hello ' ,
xtype:'person'
});
Ext.getCmp('idOfTheView').setRecord(result.first_name);
Your question is Sencha Touch alone, not relevant to PhoneGap. :)
Suppose that your view has an id: view_id
Then in your controller function:
Ext.getCmp('view_id').setHtml(what you want to put into your view)
Updated answer:
Your question consists of several sub-questions. I'm afraid that the scope you're asking is too wide but I will answer the most important part.
(from my own application):
Ext.define('rs.view.ProductInfo', {
extend: 'Ext.Container',
xtype: 'ProductInfo',
id: 'product-info',
cls: 'product-info',
config: {
items: [
{
xtype: 'panel',
styleHtmlContent: true,
id: 'product-info-header',
tpl: [
'<div class="product-info-header">',
'<img src={image} width="100px" height="100px"/>',
'<h3>{name}</h3>',
'<h4>Price: {price}</h4>',
'<h4>Seller: {sellerUsername}</h4>',
'</div>',
],
},
],
}
});
Note that I defined a Model with attributes, {image},{name},{price},{sellerUsername}, then in the code snippet above, you can see that I use them in tpl config as if normal use in Ext.List (with store config). So how can I do it?
First, you have to define a model describing your result. obviously.
Second, define tpl in your view, I believe you can figure it out from the example above.
Finally, use this (assume that you've written the result received from server into your Model instance which I've mentioned in first step):
Ext.getCmp('your_view_id').setRecord(your_model_instance)
100% work warranty because I've used this many times. Hope it helps. Should you have any question, please leave a comment.
I'm developing a Sencha Touch application in which I'm doing lots of Ext.extend and creating my own custom components and classes. I'm relatively new to the Sencha Touch realm, and I'm having a bit of a problem trying to use one of my components inside an Ext.XTemplate. Here's a concept of what I'm trying to do in some code:
MyObj = Ext.extend(Ext.Panel, {
cls: 'myClass',
layout: 'card',
scroll: 'vertical',
monitorOrientation: true,
config: myConfigObject.localObjectType,
loc: 'en_US',
initComponent: function() {
// some random init code here…
// Including:
var tpl = new Ext.XTemplate(
'<tpl for=".">',
'<tpl if="Available === true"><div class="itemAvail"></tpl>',
'<tpl if="Available !== true"><div class="itemNotAvail"></tpl>',
'<div class="formText">',
// INSERT MY VIDEO COMPONENT HERE…
'</div>',
'</div>',
'</tpl>',
{ compiled : true }
);
},
// Object definition continues, but I don't think it's germane to this discussion…
});
Ext.reg('videoList', MyApp.views.VideoList);
And now the semi-code for my Video Component that I need included above:
MyVideoComponent = Ext.extend(Ext.Panel, {
programID: null,
chapterID: null,
video: null,
videoPlayer: null,
initComponent: function() {
var progID = this.programID;
var chapID = this.chapterID;
// Set up the video object based on progID and chapID
this.videoPlayer = new Ext.Video({
id: "videoPlayer",
url: video.URL,
posterURL: video.posterURL,
fullscreen: true,
autoResume: true,
// configure listeners for play/end/error
});
// Call superclass.initComponent()
},
// Create listener callbacks for onPlay, onEnded, onError…
});
Ext.reg('videoComponent', MyApp.components.VideoComponent);
Does anyone have any ideas on how I can accomplish this?
Thanks!
[Sencha Person] Our template language currently is a bit restrictive. Once you drop into HTML for an item renderer, you cannot get back to the component level. You can achieve the desired result by extending panel as a custom component that iterates through a data list and creates and adds the items to the DOM.
We'd like to make our templating much more flexible so you can accomplish what you're looking to do more easily, but at least in Touch 1.0, it's not a basic task.
Since the code you presented is quite conceptual, I can only provide a general direction to possible solutions:
I would try to break down the content in the page into multiple components and organize them (including the video component) with the layout system provided by Sencha Touch.
When using Extjs/Sencha Touch, the "proper" way to think of views is not to write them in html, but to construct them with components in the library as much as possible.
I wanto to add a tool (search, help, gear, ...) in a window dynamically, like this:
http://www.rahulsingla.com/sites/default/files/content/blog/extjs/extjs-panel-add-tool.htm
And I need to create more than one instance of UIMyWindow at the same time.
However, I'm using Ext Designer which generates 2 files:
MyWindow.ui.js: class declaration.
MyWindow.js: methods implementation.
Besides Ext Designer hasn't an option Tools at design time (I didn't find).
I was adding the tool outside MyWindow.js and MyWindow.ui.js, like this:
var winMyWindow = new UIMyWindow({
autoShow: 'true',
tools: [{
type:'gear',
handler: function(){
// Some code...
}
}]
});
But I want to put this block inside MyWindow.js. So, I did this:
UIMyWindow = Ext.extend(UIMyWindowUi, {
tools: [{
type:'gear',
handler: function(){
// Some code...
}
}],
initComponent: function() {
UImenuDock.superclass.initComponent.call(this);
If you ask me "Why not to put this code inside MyWindow.ui.js?", I would answer "because I don't want to put this code manually every time I make changes in the design file (Ext Designer)".
Well, if I open one window, it's seems work ok, but if I open a second at the same time, the tools are duplicated in the second window...
So, any idea how to add tools dynamically in MyWindow.js in this specific case?
put 'tools' into initComponent
UIMyWindow = Ext.extend(UIMyWindowUi, {
initComponent: function() {
this.tools = [{
type:'gear',
handler: function(){
// Some code...
}
}],
UImenuDock.superclass.initComponent.call(this);