Creating components from templates (Template or XTemplate) - extjs

I'd like to be able to generate a component from within a template. The use case for it is that when I generate a row in a DataView I'd like to be able to incorporate buttons and/or other components (maybe even a nested grid) to the rendered items.
So far everywhere I look all I see is a template calling another template. Is there a way to do what I'd like (generate component instead of just plain html) from an XTemplate?

Since an XTemplate is just used for generating markup to be inserted into the DOM, it alone is not enough to create components -- Components do have an underlying DOM element (through component.el.dom), but also exist as JavaScript objects in browser memory with other methods and properties.
It is possible to accomplish what you are asking through several different ways... you can use the XTemplate to generate the markup, and use the Component.applyTo config option to create a Component object in memory that is linked to the DOM element from your template. Of course, you will have to wait until the template is applied and then create a component with applyTo set to the correct DOM element.
You could also extend the XTemplate class to do the same thing just mentioned, but wrapped up in the applyTemplate stuff. I am pretty sure that Ext does not have a built-in way for the templates to create components -- so far they just create HTML.

Related

What is the significance of parbase as cq:component's resourceSuperType

I know that i require foundation/components/parbase as a sling:resourceSuperType, as Parbase allows components to inherit attributes from other components.
As an Example, i removed parbase as resourceSuperType from foundation/components/image component and the dialog was not able to load properly as seen in the Screenshot, Crop, Rotate, Clear functionality is no longer working.
I've confirmed that Ext Js library is being loaded properly for xtype 'html5SmartImage', So what extra things does foundation/components/parbase provides for this functionality ?
Parbase allows components to inherit attributes from other components.
The above statement is a bit wrong in my opinion. It doesn't allow you to inherit attributes from other components. Rather any component which defines foundation/components/parbase as it's parent would inherit the scripts of parbase.
If you look at the parbase component within AEM, you would find a servlet which renders an image, when the URL contains img selector. Additionally you may also find a script that caters to the selector scaffolding.
Thus, whenever you define parbase or any other component inheriting from parbase as the super type for your component, you are able to use the image rendering features without the need to write separate logic for the same.
Coming to your example of the image component, the html5smartimage makes a request to the resource using the request suffix (.img.png), which is when your Image rendering servlet kicks in and draws the image. Since you have removed parbase from the super type, you would receive a 404 for the request thereby showing empty panel. However, the buttons displayed as disabled is altogether a different issue. It's a bug/feature in AEM, that when the requested image is not found, further processing of the panel stops thereby rendering them disabled.

How to hook the template rendering

My site's theme uses custom checkboxes and other items that I need to style. It uses $(".styled, input:radio, input:checkbox, .dataTables_length select").uniform(); to do so.
I'm wondering if instead of creating a bunch of directives if I can just tap into the template rendering and execute this method on the template node.
Why not just a uniform directive, which then you apply to whatever needed? There are surely things (like the .styled ones) which do not come from a template directly.

Extjs add grid panel to accordion content

I'm actually not sure if this is possible, but I will ask it anyway. I have a group of accordion controls, and within the content body of each I need to display a grid panel. The grid panel needs to have a click event attached to it. I have tried simply creating the grid panel and setting the html property of the accordion to it, but this produces no content.
Is there somehow I can achieve the above?
You cannot have html content (inserted by the property) along with any other content. If you add any item the html property value will not set/overriden. But for sure you can place anything you want into one accordion panel. Even a grid. But for that case, and based on the last question, I would recommend you to reference the view into the grid. You may do this simply by using a ComponentQuery
The click events can be applied by using the control function of the controller.
For your basic understanding:
In ExtJS you seldom use plain html code. In most scenarios you use any sort of component. All is nested within the items-array or dockedItem-array. Items within these arrays get also processed by the layout system.
Some Query examples applicable to the control function
In the following this refers to the controller itself.
You know the Id of the grid (normally you didn't do this). Id's are marke by a starting #
control({'#yourId': {itemclick: this.onItemclick }});
You know the xtype and that there is only one instance of this type. You can also describe a path by using spaces between the xtypes.
control({'grid': {itemclick: this.onItemclick }});
You have set a custom property to grid (you can refer any property this way). This one is fully compatible the the one above. I recommend this one in your case
control({'grid[customIdent=accordionGrid]': {itemclick: this.onItemclick }});
This are just some ways to use ComponentQueries, there are more. For a more detailed explanation you should refer the sencha API for ComponentQuery
Also note that every component implements the up() and down() methods which also support ComponentQueries.
I forgot to mention: For a control the query strictly need to return just one result (only the first one will be taken) a ComponentQuery on the other hand can return multiple results.
This is perfectly possible but the accordion's body is not the place to put that in. You'll need to add it to the items: [] array of the accodion. The body (or html) only accepts html.
Example:
http://docs.sencha.com/ext-js/4-1/#!/example/layout/accordion.html
this one has a grid within it.

Backbone Marionette View And Wrapping Container

Is there a way that I can tell backbone/marionette not to automatically add a the wrapping container tag when rendering a view to a region?
For example, lets say I want to display a list of items. The way I want to do that is by having one composite view looking looks this:
<ul>
</ul>
And then a item view that looks like this:
<li><%= title %></li>
Now I can easily get the same output by changing what the tag used for the auto generated element is however the biggest reason I would not have the tag automatically generated by backbone/marionette is because I want to keep as much html in the template as possible. If for whatever reason I want to change the list to a table, if all the HTML is contained in templates, I only have to change the two template files. The other way would require me to change 2 template files and 2 javascript files (less file I have to change to make a change, the less chance for error). I just like to have that level of separation of concern.
Neither Backbone nor Marionette have built in support for this. But I imagine if you could get this behaviour with a few tweaks.
Backbone.View has a method called _ensureElement that constructs the el from tagName and className if the el is not provided.
You could override _ensureElement to render the template first an then use it's first tag name as the tagName for the view. You'd also need to override Marionette.Renderer.render to strip the template's outer tag.
There maybe a better choice of methods to override to achieve this logic. I would also advise that you provide a flag somewhere to turn this behaviour on selectively so you could mix and match as needed, which would also help in debugging.

Getting HTML of GridPanel in Ext JS

I have a GridPanel which is completely ready and working. It is currently rendered to the DOM by calling the render(id) method of Ext.grid.GridPanel.
This results in the GridPanel beeing rendered right before the html element with the given id.
For programming in my API i now need the rendered HTML of the table in my JavaScript to pass it to another function which can just act on HTML code and i can't change it for compatibility reasons. So the render function doesn't return anything and i don't know how to get the html or at least a reference to the DOM-node of the rendered HTML in JavaScript.
any suggestions?
You can get the HTML of the DOM node of the body of the grid by doing:
gridObject.body.dom.innerHTML
but it is not a table... it is markup styled to look like a table...
The best way to get grid data in HTML would be to add a method to the grid that renders its data into a template.
http://dev.sencha.com/deploy/dev/docs/?class=Ext.XTemplate
Create a dom element, say d.
Then do:
Ext.fly(d).replaceWith(yourGrid.getEl())
This should replace your created dom element's contents with grid's contents. This also retains all the state, since ext component is still there.
I dont think you can actually a "String" of the HTML and pass it on to a function. But you should be able to get reference to the document element, simply by getElementById since you will know the element id (pass it into the config of the GridPanel). You'll simply get reference to the top-level element.
Have you seen the kind of HTML generated by ExtJS? They are not that nice to work directly with, it's simpler if you work with the GridPanel objects.
Its just not possible to render the table before the element exists AND IS ADDED TO THE DOM in which the grid should be rendered. That's really unflexible i think. But i am forced to use it by the project so i will have to change the API to generate some entrypoint - DIVs for the EXT grid before rendering.

Resources