I'm trying to dynamically add a component to a container with the hbox layout specified
and have that container re-size itself to accommodate the new component. Currently the
new component is added, but the new and old components are re-sized / or tiled in the
container and the container maintains its size.
Here is a demonstration of the issue I'm having on jsfiddle.
Here is the relevant extjs4 javascript for the demo:
Ext.onReady(function(){
Ext.create ('Ext.panel.Panel', {
title: 'test',
width: 300,
height: 300,
items: [
{
xtype: 'container',
layout: 'hbox',
padding : 5,
items: [
{
xtype: 'container',
id: 'textfieldgroup',
flex: 1,
height: '100%',
border: false,
layout: {
type: 'vbox',
},
defaults: {
flex: 1,
},
items: [
{
xtype: 'textfield',
emptyText: 'type here',
},
],
},
{
xtype: 'button',
flex: .1,
text: '+',
listeners: {
'click' : function () {
var textFieldGroup =
Ext.ComponentQuery.query ('#textfieldgroup')[0];
var newTextField = Ext.widget ('textfield');
textFieldGroup.add (newTextField);
},
}
}
]
}
],
renderTo: Ext.getBody ()
});
});
I have found a suitable solution and my reasoning is that you cannot have a vbox dynamically expand within an hbox container. The added benefit is that this method enables you get rid of one level of nesting. Also using the layout property autoSize: true enables the vbox container to expand and dynamically re-size itself.
Ext.onReady(function() {
Ext.create('Ext.panel.Panel', {
title: 'test',
width: 300,
height: 300,
layout: 'vbox',
items: [
{
xtype: 'fieldset',
flex: 1,
title: 'Group of fields',
width: '100%',
items: [
{
xtype: 'container',
layout: 'hbox',
width: '100%',
items: [
{
flex: 1,
xtype: 'label',
text: 'Fields',
},
{
xtype: 'button',
flex: 1,
text: '+',
listeners: {
'click': function() {
var textFieldGroup =
Ext.ComponentQuery.query('#textfieldgroup')[0];
var newTextField = Ext.widget('textfield');
textFieldGroup.add(newTextField);
},
}}
]
},
{
xtype: 'container',
layout: {
type: 'vbox',
autoSize: true,
},
id: 'textfieldgroup',
defaults : {
// flex: 1,
},
items : [
{
xtype: 'textfield',
emptyText: 'type here',
}
]
}
]}
],
renderTo: Ext.getBody()
});
});
Related
I have a Problem with Carousel From Sencha Touch 2. I'm getting a border around my App in iPhone. What should I have to do to remove this border from app?
Here is my Code:
var mainPanel = ({
xtype: 'carousel',
id: 'playersView',
ui: 'light',
flex: 1,
layout: {
type: 'fit'
},
items: [
playerLiveMonitorView,
blackPlayerLiveMonitorVie
]
});
var topPanel = ({
xtype: 'panel',
width: '100%',
height: '10%',
layout: {
type: 'vbox',
},
items: [
{
xtype: 'panel',
width: '100%',
layout: {
type: 'hbox',
},
items: [
serverBtnPanel,
logoImagePanel
]
},
roundImagePanel
]
});
this.add([topPanel, mainPanel]);
I have a controller function for my list that is being called when the list item is tapped, within this function I am trying to update a button component's text as follows:
var button = this.getPopupButton();
//reference popupButton is set within controller
button.setText('Test');
The function seems to work, and console.info(button.getText()); is reporting the update, but within the UI the text remains the default as set in the config.
Is this a bug? Or am I doing something wrong here?
These buttons are within a segmented button object:
items: [
{
xtype: 'segmentedbutton',
flex: 1,
allowDepress: true,
layout: {
align: 'stretchmax',
pack: 'center',
type: 'hbox'
},
items: [
{
xtype: 'button',
flex: 2,
id: 'PopUpButton',
text: 'Pop up test!'
},
{
xtype: 'button',
flex: 1,
id: 'Mini',
ui: 'action',
text: 'Mini test!'
}
]
}
]
Update: It might help to know that these buttons are segmented buttons within a datalist toolbar, see complete code below:
Ext.define('TestApp.view.ItemList', {
extend: 'Ext.dataview.List',
alias: 'widget.ItemList',
config: {
loadingText: 'Loading items...',
store: 'ItemStore',
cls: [
'ItemList'
],
itemTpl: Ext.create('Ext.XTemplate',
'<div>{itemData}</div>',
),
plugins: [
{
xtype: 'component',
refreshFn: function(plugin) {
//console.info('pull to refresh!');
var store = plugin.up().getStore();
console.log(store);
},
itemId: 'PullToRefresh',
loadingText: 'Loading...',
pullRefreshText: 'Pull down to refresh...',
releaseRefreshText: 'Release to refresh...',
snappingAnimationDuration: 200,
type: 'pullrefresh'
},
{
autoPaging: true,
loadMoreText: 'Load more...',
noMoreRecordsText: 'No more data in feed',
type: 'listpaging'
}
],
items: [
{
xtype: 'toolbar',
docked: 'top',
id: 'MediaToolbar',
ui: 'light',
zIndex: 3,
items: [
{
xtype: 'button',
flex: 1,
cls: 'SourceSelectButton',
id: 'SourceSelectButton',
minWidth: '',
width: 83,
iconCls: 'ItemSource1',
text: ''
}
]
},
{
xtype: 'toolbar',
docked: 'top',
height: '45px',
id: 'FeedSelectorBar',
ui: 'light',
zIndex: 3,
items: [
{
xtype: 'segmentedbutton',
flex: 1,
id: 'FeedSelectorButtons',
allowDepress: true,
layout: {
align: 'stretchmax',
pack: 'center',
type: 'hbox'
},
items: [
{
xtype: 'button',
flex: 2,
id: 'PopUpButton',
text: 'Pop up test'
},
{
xtype: 'button',
flex: 1,
id: 'TesterButton',
ui: 'action',
text: 'Latest'
}
]
}
]
}
]
}
});
Update #2: After further testing in the console using Ext.ComponentQuery.query() I have found that I can manipulate all buttons in my application EXCLUDING the ones placed within the dataview list/toolbar.
Try following changes, this is working for me:-
Give 'id' to your segmented button.
{
xtype: 'segmentedbutton',
id: 'hii', // give id to your segmented button
allowDepress: true,
layout: {
align: 'stretchmax',
pack: 'center',
type: 'hbox'
},
items: [
{
xtype: 'button',
id: 'PopUpButton',
text: 'Pop up test!'
},
{
xtype: 'button',
id: 'Mini',
ui: 'action',
text: 'Mini test!'
}
]
}
Use this code inside controller on 'itemtap' of your list.
var button = Ext.getCmp('hii'); // use your segmented button id here
button.getAt(1).setText('Test');
This problem was solved by moving my Ext.dataview.List into a Ext.panel container. This seems to be a bug with sencha touch 2.0.1.1. Any elements that I manipulated within my dataview.List toolbar component would report as updated in the console but would not show as updated in the UI. The same problem occured in both Chrome, Safari and on an Android device packaged as a phonegap project.
In my application I have a one view with topbar and some fields. In this button when I am click the login button I want to move to another view (Dashboard) which is a tabview. So for this I am using viewport. But I am unable to move from one view to another. Here is my code:
app.js
Ext.Loader.setConfig({
enabled : true
});
Ext.application({
views : ['TitlePanel', 'dashboardpanel'],
models : [ 'MyModel', 'wishlistmodel' ],
stores : [ 'name', 'wishlistsummarystore' ],
name : 'MyApp',
controllers : [ 'MyController' ],
launch : function() {
var Login = {
xtype: 'login'
}
var Dashboard = {
xtype: 'dashboard'
}
Ext.Viewport.add([Login, Dashboard]);
}
});
Titlepanel.js
Ext.define('MyApp.view.TitlePanel', {
extend: 'Ext.Panel',
alias: 'widget.login',
config: {
ui: 'light',
items: [
{
xtype: 'panel',
id: 'LoginScreen',
items: [
{
xtype: 'image',
docked: 'left',
height: 130,
id: 'Logoimage',
ui: '',
width: 170,
src: 'app/images/logo.png'
},
{
xtype: 'titlebar',
cls: 'mytitlebar',
docked: 'top',
height: 100,
ui: 'blue',
items: [
{
xtype: 'label',
height: 36,
html: 'Teritree Business Portal',
id: 'title',
margin: 20,
style: 'font: normal Bold 20px droid sans; color:#AB3951',
width: 396
}
]
},
{
xtype: 'panel',
id: 'LoginPanel',
layout: {
align: 'center',
type: 'vbox'
},
items: [
{
xtype: 'label',
html: 'Login with Teritree Business Credentials',
id: 'Loginlabel',
margin: 20,
style: 'font: normal Bold 30px droid sans',
ui: 'dark'
},
{
xtype: 'fieldset',
height: 84,
itemId: 'LoginField',
margin: '40 0 0 0',
width: 500,
items: [
{
xtype: 'textfield',
id: 'user',
style: 'font: Droid Sans',
label: 'Login User id',
labelWidth: '40%'
},
{
xtype: 'textfield',
height: 35,
id: 'password',
label: 'Password',
labelWidth: '40%'
}
]
},
{
xtype: 'button',
height: 40,
id: 'LoginBtn',
margin: 20,
ui: 'orange',
width: 180,
text: 'Login'
},
{
xtype: 'label',
html: 'If you don\'t have an account yet: Signup at business.teritree.com ',
id: 'signup',
margin: 20,
style: 'font: normal 24px droid sans'
}
]
}
]
}
]
}
});
dashboardpanel.js
Ext.define('MyApp.view.dashboardpanel', {
extend: 'Ext.Panel',
alias: 'widget.dashboard',
id:'dashboardpanel',
fullscreen: true,
tabBarDock: 'bottom',
items: [
mainWindow
]
});
var mainWindow = new Ext.Panel({
title:'main',
iconCls:'home',
layout:'fit',
scroll: 'vertical',
dockedItems: [toolbar,bigButton]
});
var bigButton = new Ext.Button({
dock: 'bottom',
text: 'I should be at the bottom'
});
var toolbar = new Ext.Toolbar({
dock: 'top',
title: 'Main',
items: [
{
text: 'Reload',
}
]
});
MyContrller.js
Ext.define('MyApp.controller.MyController', {
extend : 'Ext.app.Controller',
config : {
refs : {
LoginScreen : '#Login',
dashboardscreen : '#dashboardpanel'
},
control : {
"#LoginBtn" : {
tap : 'onLoginButtonTap'
}
}
},
slideLeftTransition: { type: 'slide', direction: 'left' },
onLoginButtonTap : function(button, e, options) {
Ext.Viewport.animateActiveItem(Dashboard, this.slideLeftTransition);
}
});
Hey i am able to solve this problem finally. Because iwas giving wrong references in controller..here is the controller code:
Ext.define('MyApp.controller.MyController', {
extend : 'Ext.app.Controller',
config : {
refs : {
TitlePanel : 'login',
dashboardpanel : 'dashboard'
},
views : [
'TitlePanel',
'dashboardpanel'
],
control : {
"#LoginBtn" : {
tap : 'onLoginButtonTap'
}
}
},
slideLeftTransition: { type: 'slide', direction: 'left' },
onLoginButtonTap : function(button, e, options) {
Ext.Viewport.setActiveItem(this.getDashboardpanel(), this.slideLeftTransition);
}
});
Ext.Viewport.setActiveItem(1);
PS: Please notice the viewport case.
Hey #Arindam just put into your MyController file like this,
Ext.define('myapp.controller.MyController', {
extend : 'Ext.app.Controller',
config : {
refs : {
LoginScreen: '#Login',
dashboardscreen : '#Dashboard'
},
control : {
"#LoginBtn": {
tap : 'onLoginButtonTap'
}
}
},
onLoginButtonTap: function(button, e, options) {
Ext.getCmp('dashboardpanel').show('slide', true)
Ext.getCmp('loginpanel').hide()
}
});
And you have some bugs into dashboardpanel.js file.
I hope this helps :)
I would suggest you to use Ext.navigation.View for this.
You can just add viewport in app.js, then in viewport add navigation view, on that navigation view you can push you TitlePanel, and then form button click in the TitlePanel, just push your dashboardpanel.
I have created a view like this
Ext.define('App.view.Message', {
extend: 'Ext.Panel',
alias: 'widget.message',
config: {
layout: 'vbox',
bigText: 'big Text',
smallText: 'small text',
imageUrl: 'imageurl',
oT: '',
description: 'message description',
items: [
{
flex: 3,
xtype: 'container',
layout: 'hbox',
items: [
{
xtype: 'container',
flex: 1,
items: [
{
html: '<h3>' + this.getBigText() + '</h3>'
},
{
html: '<h5>' + this.getSmallText() + '</h5>'
}
]
},
{
xtype: 'image',
src: this.getImageUrl(),
flex: 1
}
]
},
{
flex: 6,
xtype: 'container',
layout: 'vbox',
items: [
{
flex:1,
html: '<h3>' + this.getBigText() + '</h3>'
},
{
flex:5,
html: '<p>'+this.getDescription()+'</p>'
}
]
},
{
flex: 1,
xtype: 'button',
text: this.getOT()
}
]
}
})
i need to access values that will be passed when this view is created (config values) while creating the view.
so statement this.getDescription(), this.getBigText() etc etc are generating errors..
what i want is tht the view should be rendered with the config values that i pass is when im creating the view..
what should i do?
Looks like you have to override the constructor and get the config values:
Ext.define('App.view.Message', {
extend: 'Ext.Panel',
alias: 'widget.message',
config: {
layout: 'vbox',
bigText: 'big Text',
smallText: 'small text',
imageUrl: 'imageurl',
oT: '',
description: 'message description'
},
constructor: function(config)
{
config.items = [
{
flex: 3,
xtype: 'container',
layout: 'hbox',
items: [
{
xtype: 'container',
flex: 1,
items: [
{
html: '<h3>' + config.bigText + '</h3>'
},
{
html: '<h5>' + config.smallText + '</h5>'
}
]
},
{
xtype: 'image',
src: config.imageUrl,
flex: 1
}
]
},
{
flex: 6,
xtype: 'container',
layout: 'vbox',
items: [
{
flex:1,
html: '<h3>' + config.bigText + '</h3>'
},
{
flex:5,
html: '<p>'+config.description+'</p>'
}
]
},
{
flex: 1,
xtype: 'button',
text: config.oT
}
];
this.callParent(arguments);
}
});
Sencha Touch 2 does not automatically generate getters and setters for your config. However, there are 2 ways to do what you need:
Get & set config values directly through Ext.getCmp('your_component_id').config.bigText (similar to other configs)
Manually create getters & setters for your custom config, for example, you have to define something like this as a config of your view component:
getBigText: function(){return this.bigText;}
setBigText: function(value) {this.bigText = value;}
Hope this helps.
When you are define and load a "View" file - browser go through each line. The "View" instance isn't created at that time. So, naturally the this cannot be found there.
However, you can use "this" inside the initialize function. So, you can write your code like this:
Ext.define('App.view.Message', {
extend: 'Ext.Panel',
xtype: 'message',
config: {
layout: 'vbox',
bigText: 'big Text',
smallText: 'small text',
imageUrl: 'imageurl',
oT: '',
description: 'message description'
},
initialize : function(){
this.add([
{
flex: 3,
xtype: 'container',
layout: 'hbox',
items: [
{
xtype: 'container',
flex: 1,
items: [
{
html: '<h3>' + this.bigText + '</h3>'
},
{
html: '<h5>' + this.smallText + '</h5>'
}
]
},
{
xtype: 'image',
src: this.imageUrl,
flex: 1
}
]
},
{
flex: 6,
xtype: 'container',
layout: 'vbox',
items: [
{
flex:1,
html: '<h3>' + this.bigText + '</h3>'
},
{
flex:5,
html: '<p>'+ this.description +'</p>'
}
]
},
{
flex: 1,
xtype: 'button',
text: this.oT
}
]);
this.callParent(arguments);
}
});
For that I recommend that you add you items to the view in the initialize function like so :
...
config:{
...
},
initialize: function(){
var me = this;
me.callParent();
var container = Ext.create('Ext.Container',{
title = this.config.bigText
});
me.add(container);
}
...
I don't know if there is a best solution but this works.
A simple solution is to do that in initialize() function, eg.
this.config.title = 'my title';
this.config.iconCls = 'info';
this.callParent();
In a small program that I have, I'm trying to have custom containers for every leaf node of my Nested List.
Here are a couple arbitrary example containers that I'm trying to test with:
Ext.define('DetailContainer1', {
extend: 'Ext.Container',
xtype: 'detail-container1',
layout: {
type: 'vbox'
},
height: 300,
style: 'background-color: #a9a9a9;',
// flex: 1,
items: [{
html: 'Detail Container1'
}]
});
Ext.define('DetailContainer2', {
extend: 'Ext.Container',
xtype: 'detail-container2',
layout: {
type: 'vbox'
},
height: 300,
style: 'background-color: #c9c9c9;',
// flex: 1,
items: [{
html: 'Detail Container2',
flex: 1
}, {
xtype: 'button',
text: 'Hit me!',
flex: 1
}]
});
How can I switch in the new containers when the user clicks on the leaf node?
This action should happen in onLeafItemTap(). Btw the initial container (#2) isn't showing at the moment. Is this a layout issue?
Here's some idea of what the screen should look like:
Complete source:
Ext.Loader.setConfig({
enabled: true
});
Ext.define('DetailContainer1', {
extend: 'Ext.Container',
xtype: 'detail-container1',
layout: {
type: 'vbox'
},
height: 300,
style: 'background-color: #a9a9a9;',
// flex: 1,
items: [{
html: 'Detail Container1'
}]
});
Ext.define('DetailContainer2', {
extend: 'Ext.Container',
xtype: 'detail-container2',
layout: {
type: 'vbox'
},
height: 300,
style: 'background-color: #c9c9c9;',
// flex: 1,
items: [{
html: 'Detail Container2',
flex: 1
}, {
xtype: 'button',
text: 'Hit me!',
flex: 1
}]
});
Ext.define('ListItem', {
extend: 'Ext.data.Model',
config: {
fields: ['text']
}
});
Ext.define('Sencha.view.MainView', {
extend: 'Ext.Container',
xtype: 'mainview',
layout: {
type: 'hbox'
},
initialize: function() {
this.treeStore = Ext.create('Ext.data.TreeStore', {
model: 'ListItem',
defaultRootProperty: 'items',
root: {
items: [{
text: 'Containers',
items: [{
text: 'Detail #1',
leaf: true
}, {
text: 'Detail #2',
leaf: true
}]
}]
}
});
this.detailContainer = Ext.create("DetailContainer2", {});
this.nestedList = Ext.create('Ext.NestedList', {
docked: 'left',
width: 300,
flex: 1,
store: this.treeStore,
detailCard: true,
detailContainer: this.detailContainer,
listeners: {
scope: this,
leafitemtap: this.onLeafItemTap
}
});
this.setItems([this.detailContainer, this.nestedList]);
},
onLeafItemTap: function(nestedList, list, index, node, record, e) {
var detailCard = nestedList.getDetailCard();
// nestedList.setDetailContainer(Ext.create("DetailContainer1", {}))
// detailCard.setHtml(record.get('text') + "...");
}
});
Ext.application({
launch: function() {
var container = Ext.create("Ext.Container", {
layout: {
type: 'hbox'
},
items: [{
xtype: 'mainview'
}]
});
Ext.Viewport.add(container);
}
});
Finally I've figured out the proper way to solve your problem.
Some explanations:
If you want to display "customized detailContainer" at the right side of your hbox, it's quite obvious that you should disable detailCard config for your Ext.NestedList because it's designed to display inline (i.e. take place of your Ext.NestedList).
When using Ext.define, everything should be included in config (except extend, xtype, alias, id, so in this case, layout has to be put in config).
flex should be defined in config as well.
At leafitemtap event, simply update your detailContainer config and remove/add it again as it would not be updated dynamically.
Please take a look at modified code snippet below, it works perfectly for me.
Ext.Loader.setConfig({ enabled: true });
Ext.define('DetailContainer1', {
extend: 'Ext.Container',
xtype: 'detail-container1',
config: {
flex: 1,
layout: {
type: 'vbox'
},
style: 'background-color: #a9a9a9;',
items: [
{html: 'Detail Container1'}
]
}
});
Ext.define('DetailContainer2', {
extend: 'Ext.Container',
xtype: 'detail-container2',
config: {
flex: 1,
layout: {
type: 'vbox'
},
style: 'background-color: #c9c9c9;',
items: [
{html: 'Detail Container2', flex: 1},
{xtype: 'button', text: 'Hit me!', flex: 1}
]
}
});
Ext.define('ListItem', {
extend: 'Ext.data.Model',
config: {
fields: ['text']
}
});
Ext.define('Sencha.view.MainView', {
extend: 'Ext.Container',
xtype: 'mainview',
id: 'mainview',
config: {
layout: {
type: 'hbox'
},
},
initialize: function() {
this.treeStore = Ext.create('Ext.data.TreeStore', {
model: 'ListItem',
defaultRootProperty: 'items',
root: {
items: [
{
text: 'Containers',
items: [
{ text: 'Detail #1', leaf: true },
{ text: 'Detail #2', leaf: true }
]
}
]
}
});
this.detailContainer = Ext.create("DetailContainer2");
this.nestedList = Ext.create('Ext.NestedList', {
flex: 1,
store: this.treeStore,
listeners: {
scope: this,
leafitemtap: this.onLeafItemTap
}
});
this.setItems([this.nestedList, this.detailContainer]);
},
onLeafItemTap: function(nestedList, list, index, node, record, e) {
mainview = Ext.getCmp('mainview');
if (index==0) {
mainview.detailContainer = Ext.create("DetailContainer1");
} else {
mainview.detailContainer = Ext.create("DetailContainer2");
}
mainview.removeAt(1);
mainview.add(mainview.detailContainer);
}
});
Ext.application({
launch: function() {
Ext.Viewport.add(
Ext.create("Ext.Container", {
layout: {
type: 'card'
},
items: [
{ xtype : 'mainview'}
]
}));
}
});