I build an app for file system. Files from root directory will be load initially. After user taps a directory subfiles should be load and so on. Here is a problem: I dont know
how deep users file structure is.
Means I dont know how many views I will need.
Currently I want to make it this way(But I am happy for ideas to improve my app): User taps on a file. The controller should catch the tap event and should create a new View where loaded data should be placed in.
Thats the theory.
In praxis all my file views has a class. Lets call it 'fileStructureView'. And I have only one Controller for x-number of fileStructureViews.
In my contollers config I made it this way:
Code:
config: {
refs : {
fileStructureViews : 'list[class="fileStructureView"]'
},
control : {
fileStructureViews : {
onItem : 'onItem'
}
}
},
onItem : function() {
alert('Test');
}
In my view I set a handler on the items which fires an onItem event.
But my onItem Event will never executed.
If I choose view-ids in the refs it works, but because I have to create an unknown number of views I have to give classes to my views.
Thanks for help.
I suggest You to use routing in controller and dynamically create views. For example go to to sencha sdk and find project Touch Style.
Hope this helps
Related
I'm working in Kotlin with the TornadoFX library. Imagine you have a toolbar which shows the tool that are useful for the current view you have. So we have a MainController which has a subController property which is the controller of some view next to the tool bar. So if our subController changes, the view should update. Also, if any property (e.g. selectedTool, tools) of the subController changes, the toolbar should update accordingly. Momentarily, the toolbar is not updated.
class ToolBar : View("Tool bar") {
private val controller: MainController by inject()
override val root = vbox {
tilepane {
for (tool in controller.subController.tools) {
button(tool.name, group).action {
controller.subController.changeTool(tool) // changes selected tool
}
}
}
this += controller.subController.selectedTool.options
}
}
Extra info: subController.tools is an ArrayList and subController.selectedTool is a Tool.
Now my question is, what's the recommended way to do this in TornadoFX?
You have several options. A Parent supports a function called bindChildren which accepts an observable list of items and a function to turn each of these items into a Node. You can use this to create your buttons in the toolbar:
tilepane {
bindChildren(controller.subController.tools) { tool ->
Button(tool.name) ...
}
}
You can also do this manually if you need more control:
tilepane {
controller.subController.tools.onChange {
children.clear()
// create new buttons here, like in your example
}
}
However, instead of injecting controller to access subController to get to the tools, you should have a ToolsModel which is injected into the current scope. The tools model could have a list of tools and the selected tools and can be injected into all views and controllers which needs it. You say that selectedTool is a Tool, but you're not showing what a Tool is, but judging from your code it looks like Tool.options is a Node subclass (?).
You can add/remove the tool.options element using the same technique, or even wrap it in a stackpane or other layoutcontainer to be able to identify the tool to remove (or simply remove all children of the stackpane) on change using the same technique.
In my app I am using tpl but its not working: can any one tell me what to do and where I am wrong?
Inside config :
{
id: 'content',
tpl: "<div class='attorney-details'>hi:{details}</div>"
},
and my Update method is :
update: function(newRecord) {
if (newRecord) {
currentView=this.getRecord().data;
this.down('#content').setData(newRecord.data);
}
}
At output not even "Hi" is printed.
Also, if an alert is added in the update method it is not executed.
Thanks.
The first step would be to make sure your update method would be executed. Not really enough info to figure out what is going on with your code. It looks like your update method is located inside your view with your reference to this.down, so you need to make sure the component you are using has access to a store. If you don't you can just pass an object to update the template like this http://new.senchafiddle.com/#/7mAmV/.
I am rather new to sencha touch, I've done a lot of research and tutorials to learn the basics but now that I am experimenting I have run into a problem that I can't figure out.
I have a basic DataList which gets its data from a store which displays in a xtemplate.
Within this template I have created a member function which requires store field data to be parsed as a parameter.
I would like to make a thumbnail image (that's source is pulled from the store) execute the member function on click/tap.
I can't find any information on this within the docs, does anyone know the best way to go about this?
Here is a code example (pulled from docs as I can't access my actual code right now).
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>'
{
tapFunction: function(name){
alert(name);
}
}
);
tpl.overwrite(panel.body, data);
I want to make the paragraph clickable which will then execute the tapFunction() member function and pass the {name} variable.
Doing something like onclick="{[this.tapFunction(values.name)]} " does not seem to work.
I think functions in template are executed as soon as the view is rendered so I don't think this is the proper solution.
What I would do in your case is :
Add a unique class to your < p > tag
tpl : '<p class="my-p-tag">{name}</p>'
Detect the itemtap event on the list
In your dataview controller, you add an tap event listener on your list.
refs: {
myList: 'WHATEVER_REFERENCE_MATCHES_YOUR_LIST'
},
control: {
myList: {
itemtap: 'listItemTap'
}
}
Check if the target of the tap is the < p > tag
To do so, implement your listItemTap function like so :
listItemTap: function(list,index,target,record,e){
var node = e.target;
if (node.className && node.className.indexOf('my-p-tag') > -1) {
console.log(record.get('name'));
}
}
Hope this helps
I'am adding content to my application viewport like this:
Ext.Viewport.animateActiveItem(item, {transition})
I'am searching for a way to get "back" to the last view. Is that possible, or does the viewport destroy the last view?
Why not just use the built in history support? You can add an entry to the history object like so:
this.getApplication().getHistory().add(Ext.create('Ext.app.Action', {
url: 'dashboard'
}));
Once you call that function, it will change the application's URL hash. You can grab the event by using routes in your controller... add it to the config like so:
config: {
routes: {
'dashboard': 'showDashboard'
},
control: {
//controls...
}
},
Sencha Touch will recognize the URL change and look to your routes to call a function like so:
showDashboard: function() {
Ext.Viewport.animateActiveItem(item, {transition});
},
Using this method, the native back button will take you back to the previous view, you can also call which view you want to go to etc... view the documentation on the history object here: http://docs.sencha.com/touch/2-0/#!/api/Ext.app.History
Why don't you use the Ext.Viewport.animateActiveItem() on your first panel then ?
I did it here : http://www.senchafiddle.com/#xTZZg
Hope this helps
Ext.app.Action is a private Sencha class so cannot be guaranteed to exist in future releases. A better way is replace ...
this.getApplication().getHistory().add(Ext.create('Ext.app.Action', {
url: 'dashboard'
}));
with this ...
this.getApplication().redirectTo('dashboard');
You can also pass a Model object provided it implements a toUrl() method ...
this.getApplication().redirectTo(myModelObj);
If required, you can now just use the following to go back:
history.back();
Refer to the Touch History Guide:
http://docs.sencha.com/touch/2-2/#!/guide/history_support
I am designing an app in sencha touch2. I have a panel object in my JS file. I need to dynamically set the text/html for this component. The store for this component is defined at the application level. Following is the thing I worked out:
Ext.define('class_name',{
....
config : {
pnlObj : null,
...
}
initialize : function() {
this.config.pnlObj = Ext.create('Ext.Panel');
var store = Ext.data.Storemanager.lookup('some_store');
store.on('load',this.loadStore,this);
this.setItems([{
//some items here
{
flex : 2,
// id : 'somepnl',
config : this.config.pnlObj
}
}]);
},
loadStore : function(store, rec) {
var text = rec.get('text');
var panel = this.config.pnlObj;
// var panel = Ext.getCmp('somepanl');
panel.setHtml(text);
}
});
When I inspect the inspect the element using Firebug console, I can find the panel added there. But I am not able to set the html dynamically. no html text is set there. I tried adding it using panel.add() & panel.setItems() method which doesn't work. If I give an id to that panel(somepanel here) and try to access it using Ext.getCmp('smpanel') then in that case it works fine. I have found that using Ext.getCmp() is not a good practice and want to avoid it as it might somewhere break my code in the future.
I guess the way I am instantiating the panel object is creating some issue. Can someone suggest the best way of doing it?
The recommended way to manipulate your components in Sencha Touch 2 is using controller, through refs and control configs. For example, your panel has a config like this: xtype:'myPanel', then in your controller:
refs: {
myPanel: 'myPanel'
}
control:{
myPanel: {
on_an_event: 'set_html_for_my_panel'
}
}
Lastly, define your function:
set_html_for_my_panel: function()
{
this.getMyPanel().setHtml('my_updated_html');
}
P/S: Behind the scene, Sencha Touch 2 uses Ext.ComponentQuery for refs in controllers