Sencha Extjs6 - Modern toolkit - NestedList inside an Ext.Menu - mobile

I'm quite new to Sencha Extjs6. I'm making a universal app (focusing on the mobile right now) and I'm trying to add a NestedList into a Menu. I have the Menu sliding in from the left and I can display the NestedList, but when I drill down the items in the list get mixed up? I.e. It'll show the parent item as well as its children. If I click back to the root then it'll still display all the leaf nodes etc when it should just show the root item. There's no slide animation between the items either so it makes me think it's not currently possible to use it this way?
When I create the NestedList in isolation (not added to an Ext.Menu) then it works as expected (similar to the KitchenSink example).
This is what I have thus far:
MenuList.js
Ext.define('mobile.view.menu.MenuList', {
extend: 'Ext.NestedList',
xtype: 'menulist',
store: 'mobile.store.menu.MenuListStore',
controller: 'listcontroller',
displayField: 'text',
title: 'Menu',
width: '100%',
itemId: 'menulist',
layout: 'fit',
styleHtmlContent: true,
useTitleAsBackText: false,
backText: ' ',
scrollable: true
});
NavigationMenu.js The nested list is added to this.
Ext.define('mobile.view.menu.NavigationMenu', {
extend: 'Ext.Menu',
xtype: 'navigation',
controller: 'navigation-controller',
renderTo: document.body
...
...
...
getMenuCfg: function(side) {
var me = this;
return {
items:[{
xtype: 'menulist'
}, {
text: 'Log out',
textAlign: 'left'
...
}]
}
}
MenuListStore.js
I have my own data, but I tried it with the carregions example and still didn't change the behaviour.
Ext.define('mobile.store.menu.MenuListStore', {
extend: 'Ext.data.TreeStore',
config: {
model: 'mobile.model.menu.MenuItem',
root: {},
proxy: {
type: 'ajax',
url: 'resources/carregions.json'
}
}
});
MenuItem.js
Ext.define('mobile.model.menu.MenuItem', {
extend: 'Ext.data.Model',
config: {
fields: ['text']
}
});
In a nutshell it works as a standalone component when added to the viewport, but not when I add it as a component into a menu. Any help or guidance would be fantastic. Thanks a lot guys. :)

I managed to solve it. It seems that removing layout: 'fit' got it working.

Related

Implementing a Routing system for my Views (ExtJS)

I want to implement a route for my basic view in ExtJS so that when display it (on a button click) the URL changes and when i want to return back to the initial view it works by displaying the right view.
Giving my view class :
Ext.define('Traccar.view.newDashboard', {
extend: 'Ext.Container',
alias: 'widget.newDashboard',
id: 'geoAfricaDashboard',
routes : {
'dashboard' : ''
},
layout: {
type: 'border',
align: 'stretch '
},
height: 620,
style: {
'backgroundColor': '#909090 !important'
},
items: [{
// xtype: 'panel' implied by default
title: 'Geo-Africa Administration',
region: 'west',
xtype: 'panel',
//margin: '5 0 0 5',
width: 200,
collapsible: true, // make collapsible
id: 'west-region-container',
layout: 'fit',
items: [{
xtype: 'treelist',
store: {
root: {
expanded: true,
children: [{
text: 'Options',
leaf: true,
iconCls: 'fas fa-address-book'
}, {
text: 'Administration',
expanded: true,
iconCls: 'far fa-id-badge',
children: [{
text: 'Configuration',
leaf: true,
iconCls: 'fas fa-address-card'
}, {
text: 'User',
leaf: true,
iconCls: 'fas fa-child'
}]
}]
}
},
renderTo: Ext.getBody()
}]
}, {
xtype: 'basic-panels'
// width: '100%'
}]
Which i render on button click like so :
var dash = Ext.create('widget.newDashboard', {
renderTo: Ext.getBody(),
hideMode: 'visibility'
});
dash.show();
How can i assign a route URI to that view in ExtJS (6.2.0)?
Thank you for the great help ?
PS : i tried with
routes : {
'dashboard' : ''
},
or else this.redirectTo("dashboard"); But neither works.
The route is similar to firing an event. The end result is a function is called. The hash is passed to the function based on how the route is setup. You can either call a different function for each hash or you can use the hash, or other parts of the URI to determine what to do.
Router Documentation This web page describes how the router is used. It is a very quick read.
A common way the examples (admin dashboard, coworkee app) do it by having the hash be the xtype for the panel (view) you want to display.
So your main panel extends 'Ext.navigation.View'. Then based on the hash you create a new instance of the view, add it to the main panel and make it the active item. You can also check to see if the xtype has already been added to the navigation view and just make it the active panel.
Fiddle showing use of router (this is not mine). Here is a fiddle that shows how to use a router. I would recommend reading the docs first. THe sencha docs are actually pretty good and you can learn how to use the Extjs library as it was intended and really speed up your development.

Changing order of tabs in Ext.tab.panel without cut-paste of code manually

I am writing a code as below in Sencha Touch 2.3. Is there a way to bring the nestedlist to show up before the formpanel (it is currently after) without cutting and pasting the code manually? something like each of TabPanel's component having a Rank or an Order property that I can set? Thanks
Ext.create("Ext.tab.Panel", {
fullscreen: true,
tabBarPosition: 'bottom',
items: [
{
title: 'Home',
iconCls: 'home',
cls: 'home',
...
},
{
xtype: 'formpanel',
..
},
{
xtype: 'nestedlist',
..
}
]});
You cannot do it at definition time but you could do it at runtime by calling tabpanel.insert(newIndex, nestedList), where newIndex would be most likely 1 and nestedList is the reference to the already existing nested list.

sencha touch 2 - how to add vertically scrollable component to horizontal carousel

I've spent days on this, and seriously can't understand why it should be so hard to do what seems - to me, anyway - that it should be default behaviour. Other posts seem to be asking how to prevent the behaviour I'm hoping to achieve, so I must be doing something very wrong.
I want to put this component:
Ext.define('Proximity.view.detail.DetailPanel', {
extend: 'Ext.Panel',
xtype: 'detailpanel',
scrollable: 'true',
config: {
scrollable: 'true',
layout: 'vbox',
items: [
{
xtype: 'panel',
bodyPadding: 15,
docked: 'top',
tpl: '<h3 class="detail-name">{name}</h3>' +
'<img class="detail-image" src="http://src.sencha.io/-34/x50/{image}"/>' +
'<div class="detail-description">\"{description}\"</div>' +
'<div class="detail-address">{street}, {suburb}</div>'
},
// more items to come here
]
}
});
into this carousel:
Ext.define('Proximity.view.result.ResultCarousel', {
extend: 'Ext.Carousel',
xtype: 'detailcarousel',
config: {
store: 'RemoteResultStore',
direction: 'horizontal',
fullscreen: true,
defaults: {
styleHtmlContent: true,
scrollable: true
}
}
});
in such a way that if the content overflows the current screen I can scroll down to the bottom.
But when I add the panel as a bunch of items into the carousel, each page in the carousel is vertically-locked. Any overflow from the DetailPanel component is offscreen and totally unreachable.
Over the last few days I have tried every combination of layout, scroll, scrollable, fullscreen, docked and item stacking I can think of, all to no avail. Eventually, I want to add some buttons to the bottom of each DetailPanel, but that doesn't seem particularly achievable right now.
Is there any way to make this work? It should be simple, right?
I found the answer, and am putting it here and in the Sencha Touch forums.
It turns out there is an undocumented config option called 'scrollDock' that makes everything I was trying to do work in the way I intended.
The following code now scrolls correctly:
Ext.define('Proximity.view.detail.DetailPanel', {
extend: 'Ext.Panel',
xtype: 'detailpanel',
config: {
layout: {
type: 'vbox',
align: 'start',
pack: 'start'
},
items: [
{
xtype: 'panel',
bodyPadding: 15,
cls: 'detail-panel',
layout: 'fit',
scrollDock: 'top',
tpl: '<h3 class="detail-name">{name}</h3>' +
'<img class="detail-image" src="http://src.sencha.io/-34/x50/{image}"/>' +
'<div class="detail-description">\"{description}\"</div>' +
'<div class="detail-address">{street}, {suburb}</div>'
},
// more stuff here
]
}
});
I'm really not sure why this does not deserve documentation. Maybe someone from Sencha could enlighten us?
Anyway, I found my clue here: http://www.sencha.com/forum/showthread.php?250883-Container-on-top-of-a-list
Cheers!

ExtJs: Ext.grid.Panel: Grid refreshes automatically and becomes blank

I am using a Grid to display data on a modal window.
It has two columns, 1. Label 2. TextField
The problem I am facing is whenever I enter anything in the textfield and lose focus from that textfield (by pressing TAB or clicking somewhere else), the grid clears itself completely and I get a blank grid!
I know this has something to do with the autoSync property of the Store associated with the grid.
So I set it to false autoSync: false.
After doing this the data gets retained and works fine.
BUT when I close this modal window and re-open it with the same store data, I get a blank screen!
Following is my code:
Model
Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'attribute',
type: 'string'
},
{ name: 'attributeValue',
type: 'string'
}
]
});
Store
var attrValueStore = Ext.create('Ext.data.ArrayStore', {
autoSync: true, //tried setting it to false but got error as mentioned above
model: 'Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueModel'
});
GRID
Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueGrid', {
autoRender: true,
extend: 'Ext.grid.Panel',
alias: ['widget.attributevaluegrid'],
id: 'SQLAttributeValueGrid',
store: attrValueStore,
columnLines: true,
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})],
columns: [
{ /*Expression */
xtype: 'gridcolumn',
text: 'Attribute',
sortable: false,
menuDisabled: true,
flex: 0.225,
dataIndex: 'attribute'
},
{ /*Attribute Values*/
xtype: 'gridcolumn',
editor: 'textfield',
text: 'Values',
flex: 0.225,
dataIndex: 'attributeValue'
}
],
initComponent: function () {
this.callParent(arguments);
}
});
MODAL WINDOW
var attributeValueForm = Ext.create('Ext.window.Window', {
title:'Missing Attribute Values',
id: 'attributeValueForm',
height:500,
width:400,
modal:true,
renderTo: Ext.getBody(),
closeAction: 'hide',
items:[
{
xtype: 'attributevaluegrid',
border: false,
//height: 80,
region: 'center',
split: true
}
],
buttons: [
{
id: 'OKBtn',
itemId: 'OKBtn',
text: 'OK',
handler: function () {
Ext.getCmp('attributeValueForm').close();
}
},
{
text: 'Cancel',
handler: function () {
Ext.getCmp('attributeValueForm').close();
}
}
]
});
Please help. This is making me go mad!!
It would be helpful if you could provide details on how you create the Window itself, as it may be part of the problem.
One cause of this can be that you are hiding the window instead of closing it and then creating a new instance when you re-open. This will cause your DOM to have two windows instances and may not sync the data correctly in the second instance.
Some more details on how you create the actual window would help shed some light on whether this is the case.
I would probably want to jail myself after writing this.
The real issue was that I had created a similar grid for a different modal window and since I had copied the code I missed out on changing the ID of the new grid.
Both grids had the same IDs.
Changed it now and it is working fine now.
Thanks for your help!

Sencha Touch 2: How do you use a button on the homepage to navigate to other views?

If you were going to take the "Getting Started with Sencha Touch 2" video one step further and add button navigation on the home page to allow you to go to the Blog and Contact pages how would you do it? I have set it all up like the thread Sencha Touch 2 MVC - how to switch views with button
The problem that I am running into is that if I create a button to go to the Blog page in the Home.js page the button will work but then the nested list on the Blog.js page does not work anymore and the TitleBar from Main.js does not appear on Blog.js anymore either. My controller code looks like this
control: {
'blog list': {
itemtap: 'showPost'
},
'button[go]':{
tap: function(){
Ext.Viewport.setActiveItem({
xtype: 'blog'
})
}
}
}
Where showPost is the same function as the GS video. My button on the Home.js file looks like this
items:[
{
xtype: 'button',
text: 'text',
go: 'buttonPage'
}]
}
Everything else is exactly like the GS video. I want the button on the Home.js page to act exactly like the buttons on the TitleBar work in Main.js from the Getting Started video. What am I missing? Thanks in advance.
4/13/12 Update: all the js files. They are all essentially the original GS video code.
view/Main.js
Ext.define("GS.view.Main", {
extend: 'Ext.tab.Panel',
requires: ['Ext.TitleBar'],
config: {
xtype: 'bottombar',
tabBarPosition: 'bottom',
items:[{xtype: 'homepanel'},
{xtype: 'blog'}]}
});
view/Home.js
Ext.define('GS.view.Home', {
extend: 'Ext.Panel',
xtype: 'homepanel',
config: {
title: 'Home',
iconCls: 'home',
items:[{
xtype: 'button',
text: 'text',
go: 'buttonPage'}]
}
})
view/Blog.js
Ext.define('GS.view.Blog',{
extend: 'Ext.navigation.View',
xtype: 'blog',
requires: ['Ext.dataview.List', 'Ext.data.proxy.JsonP', 'Ext.data.Store'],
config: {
title: 'Blog',
iconCls: 'star',
items: [{
xtype: 'list',
itemTpl: '{title}',
title: 'Recent Posts',
store:{
autoLoad: true,
fields: ['title', 'author', 'content'],
proxy: {
type: 'jsonp',
url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://data.9msn.com.au/Services/Service.axd/feeds/rss/news/headlines',
reader: {
type: 'json',
rootProperty: 'responseData.feed.entries'
}
}
}
}]
}
})
controller/Main.js
Ext.define('GS.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
blog: 'blog'
},
control: {
'blog list': {
itemtap: 'showPost'
},
'button[go]':{
tap: function(){
Ext.Viewport.setActiveItem({
xtype: 'blog'
})
}
}
}
},
showPost: function(list, index, element, record){
this.getBlog().push({
xtype: 'panel',
title: record.get('title'),
html: record.get('content'),
scrollable: true,
styleHtmlContent: true,
})
}
});
app.js
Ext.application({
name: 'GS',
requires: ['Ext.MessageBox'],
controllers: ['Main'],
views: ['Main', 'Home', 'Blog'],
launch: function() {
Ext.Viewport.add(Ext.create('GS.view.Main'));
},
});
Since using Ext.Viewport.setActiveItem({xtype: 'blog'}) doesn't reuse the xtypes that you have created it gets confused when trying to use the blog list. I use some of what Roberto said and a little bit of my own code to end up with the controller 'button[go]' function looking like this:
'button[go]':{
tap: function(btn){
if(Ext.ComponentQuery.query(btn.go) == '')
{
Ext.Viewport.setActiveItem({
xtype: btn.go
})
}
else
target = Ext.ComponentQuery.query(btn.go);
Ext.Viewport.setActiveItem(target[0])
}
}
And that created the xtype the first time and then reused it every subsequent time so the navigation in the nexted list worked as well as the navigation on the homepage
you can easily switch views by button tap if you are using navigationView.
take your main view as navigationView .
put the button into the navigationView .
write the following code into tap-listener of your button
this.up('your navigationView xtype').push({
xtype: 'xtype of the view at which you wanna go by button tap'
});
2 Steps You have to follow
in View
{
xtype: "button",
//text: "Book Bus Ticket",
ui: 'action',
action:"book" , // button Action
},
{
xtype: "button",
text: "Get Ticket Details",
ui: 'action',
action:"getticket" , // button Action
},
Note the Button Action
2.in Controller
first specify the particular view xtype as a ref in that controller
Ext.define('jetbus.controller.BookticketController', {
extend: 'Ext.app.Controller',
refs: {
'busdetails':"busDetailsList", // object:xtype
},
control: {
'busdetails button[action=book]': { // button action
tap: 'book'
},
' button[action=getticket]': { // button action
tap: 'getticket'
},
}
book: function(){
var mn=Ext.create('abc.view.Main'); // Functionname the page you want to redirect
Ext.Viewport.add(mn);
Ext.Viewport.setActiveItem(mn);
},

Resources