Extjs add grid panel to accordion content - extjs

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.

Related

Attach additional functionality to parent controller in Angular

I have a dropdown element directive to display in essence a styled dropdown list with additional capabilities.
My dropdown controller has a function called openDropdownItems that get's executed when the list should be displayed.
Then I also have another attribute directive called setInViewWhen that provides an expression when the element should be scrolled into view when condition is true.
<x set-in-view-when="something.item === selectedItem">
This is just an example of some X element with my attribute directive applied.
The thing is that I would like my dropdown list items (LIs namely) to have this directive on them so when user navigates over them using a keyboard, it would automatically scroll them in view when they get passed visible viewport. Whether these items are displayed within a scrollable container or as a whole in a list longer than the browser viewport isn't really relevant.
The main idea is for scrolling to follow dropdown list selection. Whether that should scroll the main window.
The problem
I can make my setInViewWhen directive completely independent but that means that I would have to search for the closest scrollable container whenever condition changes on an item. This seems to be quite a bit of processing that I would like to avoid to repeat (I need to traverse the DOM upwards, checking each node's calculated stylesheet property OverflowY + some additional checks.
This basically seems redundant because whenever I get the closest scrolling ancestor all sibling elements with the same directive could reuse the calculation result.
Question 1
How can I share this knowledge between sibling directives? If I was to fire an event I could not know whether receivers are siblings or not without any additional processing.
Question 2
Instead of checking for scrollable container every time when my directive's condition becomes true I could theoretically change dropdown parent's openDropdownItems to first complete it's original execution an then also execute the scrollability check and use the result of it along with my directive's condition.
I can gain access to dropdown's controller in my directive via directive requires property and adjust it in the post-link phase.
But this also means that I couldn't use my directive outside of dropdown which I would like to as it is a generally usable directive I could attach on several elements in my app to scroll elements into view under certain conditions.
What would you suggest how to do this?
To sum up the comments:
For Question 1, there is no direct way for sibling directives to communicate with each other. I usually create a wrapper parent directive to relay the messages.
As per the comments, the condition something.item === selectedItem introduces a watch; for a list of select items this can be many watches and detrimental to performance. Even if it doesn't occur now, it is a trap and someone may be lured into using this for a long list of items in the future. I would rather have a single watch in the parent of the <li>s and add the "scroll into view" logic there.
With the previous point in mind, you could still have a standalone setInViewWhen directive (seems useful) and have the controller of your X-select replacement directive share code with it. E.g.:
a service containing the common functionality,
an angular value containing a base class (Typescript or JS) and have the controller of both the setInViewWhen and X directives extend from it
or any other solution that is convenient for your case
Related to Question 2: The children could require their parent and change a method in it (this technique is even endorsed by Angular, see ng-model and custom controls where they override ngModel.$render() by replacing it). If you do that however, there would be many children changing the method of the parent, which could lead to a mess.

How to get ng-grid to hide certain rows

I have an array of objects that I want to show in ng-grid. Each row has a boolean property isVisible. In the ng-grid I want to show only the rows where isVisible is true. The other rows should be completely hidden.
I have tried using a rowTemplate and databinding a ng-show to isVisible. That hides the content of the row, but leaves the actual row in place, showing an empty row.
I have tried using filterOptions, but can't figure out the correct syntax to do such a filtering. I couldn't find any good documentation on how to set it.
I have even tried modifying the gridTemplate in the ng-grid source, by trying to add a filter on ng-repeat=\"row in renderedRows\", but I haven't gotten that to work either.
I guess I could modify the array itself, by temporarily removing rows, but I would prefer not to do it that way, since I have to be able to show the rows again (It is actually an expander that I'm doing, that should hide/show sub-rows)
Try also conditionally setting the height of the row in the template to '0' based on isVisible or use a CSS class with ng-class. Play with the CSS of it until you get the desired effect and then you can use that in your template.
This sounds like the type of thing that would benefit from using height and CSS animations actually so it opens and closes with an animated style. If you have a jsFiddle sample I'd be happy to try and help.
Edit: After looking at how the grid actually lays out it's rows (absolutely positioned) you only really have two options I can think of:
1) Filter the data you are binding to the grid through a function like dataVisible() but keep the full data list internally in the controller so you can show/hide easily
2) Submit a patch to the ng-grid project (or fork it) with the filtering capability you are looking for. Out of the box it doesn't appear to support this scenario.

How to access toolbar object of nestedlist view from another view's callback in sencha touch?

I am new in Sencha Touch, so I don't know it's full structure. So the question is a little stupid, i guess :)
I have a view it is a nestedlist object. I have created a toolar object inside my nestedlist. Now I want to manipulate this toolbar from another view's callback. How can I access my toolbar object located in nestedlist view from event callback from another view object?
With that little information on your structure (are you using the MVC pattern? No example code given) I can only say that you can definitely achieve this with Ext.ComponentQuery
Lets say you added a custom property to your toolbar named ident='myToolbar' then you can access this toolbar (precisely said any toolbar with that custom property) by calling
Ext.ComponentQuery.query('[ident=myToolbar]')[0]
The result will be always a array but in this example we accept only one result, that is why I added [0]
For further information refer to the API. Ext.ComponentQuery is mighty if you know how to use it.
First give your toolbar an id, for example myToolbar. Then, in your callback, you can do something like this
var toolbar = Ext.getCmp('myToolbar');
to get your toolbar object. Next you can manipulate the toolbar using the toolbar variable, for example change the title:
toolbar.setTitle('New Title');
More info about getCmp() here.
More info about the toolbar here (Check the toolbar's methods to manipulate 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.

Difference between "applyTo" and "contentEl" in extJS

What is the difference between applyTo and contentEl in extJS? They are two config properties of the panel.
applyTo renders the panel into a target element (the panel body could still contain any content), contentEl uses the target element as its body content (the panel could still be rendered to any other element). The two methods are unrelated.
Edit: Just a note that as of Ext 4.0+ the applyTo config no longer exists. As time went on, the declarative / progressive enhancement strategy became less viable for Ext (it never was fully supported in all components anyway), and they finally stopped supporting it. You would always use renderTo now (to render programmatically to a target element), whereas contentEl is still valid and still indicates the element from which to take content and add it into the panel's body.contentEl is most useful when you have some existing HTML on the page that you want to display inside a Panel component without having to reproduce the content markup in JS code.
While I'm here, I suppose I'll clarify something else... It's important to understand that renderTo is typically only used by the top-most container in an application layout. All child components should always be added as items to a Container -- rendering child components directly to a target element via renderTo means that those components will not participate in the Ext-managed layout system, which you typically do NOT want in an application.
Another difference is that every component in Ext supports renderTo, but only certain components (most usefully Panel) will honor contentEl in a meaningful way. Even though contentEl is defined on AbstractComponent, most components are not designed to handle arbitrary HTML content.
Generally, applyTo uses the specified element as the main element of the Component, while contentEl is only for Panels that simply moves the specified element into the body of the Panel when the Panel is rendered to use as the content!

Resources