Including a Sencha Component inside an XTemplate - sencha-touch

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.

Related

Is it possible to insert EXT Components into an XTemplate?

I have an XTemplate and I would like to add some actual EXT widgets inside the template so that I have template code rendered above and below the widgets. Let's say I have a "dataview" with the following itemTpl defined:
itemTpl: [
'<tpl for=".">',
'<div class="song-page-header">',
' <div class="artwork"><img src="{artwork}"/></div>',
' <h1>{title}</h1>',
' <h2>{artist}</h2>',
' <h3>Genre: {genre}</h3>',
' <p>{copyright}</p>',
'</div>',
/* Ext.Button should go here */
'<tpl for="offers">',
' <p>{offer_id}: {offer_type}, {price}</p>',
'</tpl>',
'</tpl>'
]
Is it possible to define a real Ext.Button there (and not just some HTML approximating the behavior of an Ext.Button)? I don't care if it has to be applied after the fact, but I can't seem to find the correct event handler to use to be able to insert a button there. The Sencha documentation sucks so any help would be greater appreciated.
Actually you can do this, you just have to be a little bit creative.
Check out my blog post here: http://jakes-hackerblog.herokuapp.com/blog/2013/05/23/a-fresh-rails-blog/
Essentially, you put some dynamic div element in your template
'<div id="box-holder">' +
'<div id="box-{schoolpersonid}"></div>'+
'</div>'+
Then you use the use "renderTo" within your button config, calling it in a refresh funciton:
listeners: {
'refresh': function(records) {
var storeRecords = records._store._data.items;
for(var i = 0; i < storeRecords.length; i++){
var data = storeRecords[i].data;
var renderTo = this.element.select('#box-' + data.schoolpersonid).elements[0];
var button1 = new Ext.Button({
action: 'doPresent',
xtype: 'button',
align: 'right',
text: 'Present',
ui: 'present',
renderTo: renderTo,
schoolpersonid: data.schoolpersonid
});
}
}
},
I think XTemplate does not support this feature due to managment and performance of Sencha Touch framework.
Secondly, you cannot do like that because basically you're trying to merge between HTML and javascript inside your itemTpl when sencha template only allow html structure.
In order to address this scenario, you may take a look at Component Dataview

Sencha Touch 2 carousel.setItems() not working

I am trying to build a dynamic image carousel using Sencha Architect. I have a carousel added to a tab panel. The carousel is set up to read images from a store called "pictureStore." I have a function to pull images from the store and create the carousel items - I can get the images from the store but unable to create the carousel. When I try to use carouself.setItems() or carousel.add() I get an error "Object # has no method". Please take a look and let me know if my method is incorrect for creating a dynamic carousel. I appreciate your help and knowledge of how to fix
Thanks,
Function to read images and create carousel items (works up until comment below):
onMycarouselActivate: function(container, newActiveItem, oldActiveItem, options) {
Ext.getStore('pictureStore').load(function(pictures) {
var items = [];
Ext.each(pictures, function(picture) {
console.log(picture.get('image'));
if (!picture.get('image')) {
return;
}
items.push({
xtype: 'myimage',
picture: picture
});
});
//following doesn't work for adding the carousel images:
//carousel.setItems(items);
//carousel.add(items);
//carousel.items = [{html: items}];
//carousel.add(carousel.items);
//carousel.setActiveItem(0);
});
},
Sample JSON with image info
{
"test": {
"cat": {
"entries": [
{
"image": "/images/1.png"
},
{
"image": "/images/2.png"
}
]
}
}
}
Error messages when using carousel.add or carousel.setItems:
Object #<HTMLDivElement> has no method 'add'
Object #<HTMLDivElement> has no method 'setItems'
If your variable carousel has no method add or setItems then it's probably not your carousel.
To make sure of that, you can try to do console.log(carousel); to figure out what it is exactly. Also, it doesn't seem to be declared anywhere in your code...
But it's quite simple to fix. I presume you've added a event listener to your carousel that listens to the activate event and if you take a look at the documentation for this event, you can see that the first parameter sent to the callback function is the container (in this case your carousel)
So what you have to write is this :
onMycarouselActivate: function(carousel, newActiveItem, oldActiveItem, options) {
instead of this
onMycarouselActivate: function(container, newActiveItem, oldActiveItem, options) {
and you should be all set
EDIT
Also if you take a look at the documentation for the image component, you can see there is no picture in the config but there is a src attribute. SO you should write :
items.push({
xtype: 'myimage',
src: picture
});
Hope this helped
try this code
myCarousel.add({
xtype: 'image',
scr:'path of image'
});
where myCarousel is object of carousel.
You can try this, this is working for me.....
Ext.getStore('Pictures').load(function(pictures) {
Ext.each(pictures, function(picture) {
if (picture.get('image')) {
carousel.add({
html: '<img style="max-width: 100%; max-height: 100%;" src="' + picture.get('image') + '"/>'
});
}
});
});
Hope this will help you...

How to make a Dojo dijit form programmatically

Im new to Dojo and im trying to make some ui, but only using the programmatic way.
I would like if someone could show me some example of how to make a form programmarically using Dojo dijit.form.Form. I've been looking for some example but all i can find is the declarative way of it.
A more object oriented solution:
define( [
"dojo/_base/declare",
"dijit/form/Form",
"dijit/form/Textarea",
"dijit/form/Button"
],
function(declare, Form, TextArea, Button) {
return declare( "mypackage.MyForm", Form, {
textarea: new TextArea({}),
submitButton: new Button({
type: "submit",
label: "ready!"
}),
constructor: function(args) {
declare.safeMixin(this, args);
},
onSubmit: function() {
alert(this.textarea.get('value'));
},
postCreate: function() {
this.domNode.appendChild( this.textarea.domNode );
this.domNode.appendChild( this.submitButton.domNode );
}
});
}
);
Just drop a new mypackage.MyForm({}) at any place you might expect a widget.
Its pretty straight forward. You just create all the pieces of the the form, and then append all the pieces to their respective parent. To create the form objects, like any dijit object, you pass the constructor a param object, and a domNode to place it at, like so:
var resetbtn = new dijit.form.Button({
type: 'reset',
label: 'Reset'
}, dojo.doc.createElement('button'));
The full example is here. To find out what properties can be added to the params object, see the API Docs. Any of the properties can be added to the param list.

Dojo/Dijit TitlePane

How do you make a titlePane's height dynamic so that if content is added to the pane after the page has loaded the TitlePane will expand?
It looks like the rich content editor being an iframe that is loaded asynchronously confuses the initial layout.
As #missingno mentioned, the resize function is what you want to look at.
If you execute the following function on your page, you can see that it does correctly resize everything:
//iterate through all widgets
dijit.registry.forEach(function(widget){
//if widget has a resize function, call it
if(widget.resize){
widget.resize()
}
});
The above function iterates through all widgets and resizes all of them. This is probably unneccessary. I think you would only need to call it on each of your layout-related widgets, after the dijit.Editor is initialized.
The easiest way to do this on the actual page would probably to add it to your addOnLoad function. For exampe:
dojo.addOnLoad(function() {
dijit.byId("ContentLetterTemplate").set("href","index2.html");
//perform resize on widgets after they are created and parsed.
dijit.registry.forEach(function(widget){
//if widget has a resize function, call it
if(widget.resize){
widget.resize()
}
});
});
EDIT: Another possible fix to the problem is setting the doLayout property on your Content Panes to false. By default all ContentPane's (including subclasses such as TitlePane and dojox.layout.ContentPane) have this property set to true. This means that the size of the ContentPane is predetermined and static. By setting the doLayout property to false, the size of the ContentPanes will grow organically as the content becomes larger or smaller.
Layout widgets have a .resize() method that you can call to trigger a recalculation. Most of the time you don't need to call it yourself (as shown in the examples in the comments) but in some situations you have no choice.
I've made an example how to load data after the pane is open and build content of pane.
What bothers me is after creating grid, I have to first put it into DOM, and after that into title pane, otherwise title pane won't get proper height. There should be cleaner way to do this.
Check it out: http://jsfiddle.net/keemor/T46tt/2/
dojo.require("dijit.TitlePane");
dojo.require("dojo.store.Memory");
dojo.require("dojo.data.ObjectStore");
dojo.require("dojox.grid.DataGrid");
dojo.ready(function() {
var pane = new dijit.TitlePane({
title: 'Dynamic title pane',
open: false,
toggle: function() {
var self = this;
self.inherited('toggle', arguments);
self._setContent(self.onDownloadStart(), true);
if (!self.open) {
return;
}
var xhr = dojo.xhrGet({
url: '/echo/json/',
load: function(r) {
var someData = [{
id: 1,
name: "One"},
{
id: 2,
name: "Two"}];
var store = dojo.data.ObjectStore({
objectStore: new dojo.store.Memory({
data: someData
})
});
var grid = new dojox.grid.DataGrid({
store: store,
structure: [{
name: "Name",
field: "name",
width: "200px"}],
autoHeight: true
});
//After inserting grid anywhere on page it gets height
//Without this line title pane doesn't resize after inserting grid
dojo.place(grid.domNode, dojo.body());
grid.startup();
self.set('content', grid.domNode);
}
});
}
});
dojo.place(pane.domNode, dojo.body());
pane.toggle();
});​
My solution is to move innerWidget.startup() into the after advice to "toggle".
titlePane.aspect = aspect.after(titlePane, 'toggle', function () {
if (titlePane.open) {
titlePane.grid.startup();
titlePane.aspect.remove();
}
});
See the dojo/aspect reference documentation for more information.

Dojo: create programatically a menu in an enhancedgrid

I'm trying to create programatically an EnahncedGrid with a menu. I've got the grid to work, but I've been unable to use the menu. It just not shows up. The code is as follows:
<script>
sMenu = new dijit.Menu({});
sMenu.addChild(new dijit.MenuItem({
label: "Delete Record",
iconClass: "dijitEditorIcon dijitEditorIconCancel",
onClick : function(){
alert(1);
}
}));
sMenu.startup();
/**
* El grid propiamente dicho
*/
var grid = new dojox.grid.EnhancedGrid({
id: "grid_"+i,
query: {
idDocument: '*'
},
plugins: {
nestedSorting: true,
indirectSelection: true,
menus: {rowMenu:sMenu}
},
onRowDblClick: openFile,
structure: layout
})
</script>
Any idea what I'm doing wrong?
I haven't used this myself, but I have two possible suggestions:
First, make sure you're dojo.require-ing "dojox.grid.enhanced.plugins.Menu" and are only instantiating the widgets within a dojo.addOnLoad or dojo.ready.
If you've already done that, the second thing I'd suggest is giving your menu an id, and passing that id to the rowMenu property of the menus object (in other words, pass a string, not the widget itself). Although, the way you're doing it seems like it should work, judging from the code.
You can see a test page with working menus here: http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/grid/tests/enhanced/test_enhanced_grid_menus.html