ExtJS ref to panel element with specific title - extjs

I am working on a project in ExtJS 4.2 written in the MVC pattern. I need a reference to a specific item inside MyViewport (extended from the class Ext.container.Viewport). The item which needs to be referenced from within the controller has the Class MyPanel (extended from "Ext.Panel"). Problem is there are several items with the same class, so simply doing a standart ExtJs-component-query like,
//inside myController.js
refs: [
...
{ref: 'specificItem', selector: 'MyViewport_alias > myPanel_alias'},
...
]
wont get me a reference to the item. Thats why i thought of retrieving the reference by something like this, since the items using MyPanel-class have a property title:
//inside myController.js
refs: [
...
{ref: 'specificItem',
selector: 'MyViewport_alias > myPanel_alias > title="title of specific item"'},
...
]
But i coulnd't find any examples on retrieving items as references by using their properties as parts of the component query other than this.
Has someone experience with this kind of problem?

Component queries in ExtJS are very similar to CSS query selectors. You could find a component by a specific property with syntax similar to: "... > [title=My Component Title]" - that said, using the "title" sounds like really bad practice.
At worst, as a visible part of the user-interface it's very sensitive to change - easily breaking your application and at best it immediately limits your application's language-support and configurability.
Ideally you should be utilising the itemId property as a more robust way of referencing components.
» fiddle
I hadn't noticed that 4.2 didn't support attribute selectors - the component query functionality seems to have always drawn inspiration from CSS though, so unfortunately if it's only a recent development it doesn't look like there's any way to do what you want using this method.
You'd have to manually fetch the component and/or create your own reference. You can select by xtype / alias in 4.2 and then apply a filter to the result, for example:
Ext.Array.filter(Ext.ComponentQuery.query('panel'), function(x){
return !!x.title.match('Sub Panel 2');
}).shift();
( Obviously no use in a controller's refs )
» fiddle
... this is however ugly - all the more reason to use itemId's properly. There was already an example of this in action in the first fiddle. All you need to do is assign an alphanumeric string (no spaces) to the property - these don't strictly need to be unique but it's generally preferable. Then in your selector simply prefix a hash # in front of the string which indicates to the engine that you are looking for a component with a specific ID.
itemId selectors definitely work in 4.2 so without seeing your code I can only speculate as to what the problem is. In your post you are using > which narrows the query to direct descendants only. Are you absolutely sure that the component you are looking for is a child of myPanel_alias and not wrapped up in another container? i.e.
"myPanel_alias #myItemId" <-- try this
"myPanel_alias > #myItemId" <-- instead of this

Related

renderTpl() intricacies

The Ext.Component "renderTpl" property default value is:
'{%this.renderContent(out,values)%}'
Where can I find a detailed explanation about that mechanism?
Where is that "renderContent" method defined? Can't find any reference in the documentation.
It seems that certain methods are dynamically created:
The renderTpl contains calls to render things like docked items,
container items and raw markup (such as the html or tpl config
properties). These calls are to methods added to the Ext.XTemplate
instance by #setupRenderTpl. The #setupRenderTpl method adds methods
such as renderItems, renderContent, etc. to the template. These are
directed to "doRenderItems", "doRenderContent" etc..
That means that setupRenderTpl and renderContent are virtual methods added on the fly?
Where can I find more info. about this?
Thanks.

Query for child component with a specific xtype

Is there a method to query for a child component of xtype 'yourxtype' ?
For example you have a panel, and inside this panel is a custom xtype located on a toolbar.
The findParentByType works great for looking up, but there is not method like findChildByType.
And the down method works only on elements. The Ext.ComponentQuery is a singleton, but not for xtypes?
Is there another way to query from a component down?
yourCt.down will find the first instance of a container with the specified type, in the component's children and descendants.
yourCt.child will do the same, but restrict to the direct children of the container.
yourCt.query will find all of the matching components underneath the container, as an array.
yourCt.up will find the first parent of the container that matches.
Oh, and Ext.ComponentQuery.query can take an optional object that is used as the start point for the query.
These are all based off (and clearly documented in) Ext.ComponentQuery
There is also a down method for component queries, but it is only available for containers. And component queries looks in xtypes for identifiers with no prefix (eg. "#", ".", etc.), it has no importance if the xtype is defined by Ext or your self. So jut do:
var child = yourCt.down('yourxtype');
This worked for me
This returns an array of instances with the mention xtype.
Ext.ComponentQuery.query('fieldxtype')
This returns only single instance i.e if we have 5 instances of the xtype.it will return only first instance of the xtype
formpanel.down('fieldxtype')
if you want get an component by name you can use
var componentArray = Ext.ComponentQuery.query('[name=checkboxName]');
var componentObj = Ext.ComponentQuery.query('[name=checkboxName]')[0];
You can simply query using
Ext.ComponentQuery.query('myXtype') this will return an array of all instances of your type.

Can AngularJS ngClass expressions be nested?

I'm new to AngularJS and have been assigned a maintenance task on an app we've inherited (originally developed for us by a third-party).
At the left of a header row in a table is a small button showing either a plus (+) or minus (-) symbol to indicate whether it will expand or collapse the section when clicked. It does this using ngClass as follows.
ng-class="{false:'icon-plus',true:'icon-minus'}[day.expanded]"
I have to remove the button when there is no data in the section and thus no ability to expand. There is already a class (.plus-placeholder) for this and I was wondering if the expressions that ngClass uses can be nested to allow something like this
ng-class="{false:'plus-placeholder',true:{false:'icon-plus',true:'icon-minus'}[day.expanded]}[day.hasTrips]"
which would allow me to add a hasTrips property to day to accomplish the task.
If this is not possible I think I will need to add a property something like expandoState that returns strings 'collapsed', 'expanded' and 'empty'. so I can code the ngClass like this
ng-class="{'collapsed':'icon-plus','expanded':'icon-minus','empty':'plus-placeholder'}[day.expandoState]"
And perhaps this is a cleaner way to do it in any case. Any thoughts/suggestions? Should it be relevant, the app is using AngularJS v1.0.2.
You certainly can do either of the two options you have mentioned. The second is far preferable to the first in terms of readable code.
The expandoState property you mention should probably be a property or a method placed on the scope. Your attribute would then read something like
ng-class="{'collapsed':'icon-plus','expanded':'icon-minus','empty':'plus-placeholder'}[expandoState()]"
To put this method on the scope you would need to find the relevant controller. This will probably be wherever day is assigned to the scope. Just add
$scope.expandoState = function() {
// Return current state name, based on $scope.day
};
Alternatively, you could write a method on the controller like
$scope.buttonClass = function() {
// Return button class name, based on $scope.day
};
that just returns the class to use. This will let you write the logic from your first option in a much more readable fashion. Then you can use
ng-class="buttonClass()"

Backbone view based on model from collection, how to update view?

I am looking for a bit of direction I am still fairly new to Backbone and am currently creating a test application to learn more.
My problem is this, I am populating a backbone view with a underscore template. I load a collection of models, then I find the model I need and populate these values into the template. There can be many pages based on the template so I have a dynamic route that accepts an id.
My problem is I want to add a next feature, that would change the current page and reload the template with the new model.
I have tried a crude method along the lines of :
Backbone.history.navigate(newLocation)
However this did'nt work, please note newLocation is actually populated with the route and the id I want to navigate to.
I will add some code from my view below, I won't include the full code however if it is needed please ask.
Any help or a push in the right direction would be great.
Thanks in advance
You need to use your router object's navigate method rather than than history's class method, and you need to pass it the option `{trigger: true} in order to invoke the corresponding route function.

Ext JS: what is xtype good for?

I see there are lot's of examples in Ext JS where instead of actually creating Ext JS objects, an object literal with an xtype property is passed in.
What is this good for? Where is the performance gain (if that's the reason) if the object is going to be created anyway?
xtype is a shorthand way to identify particular components: panel = Ext.Panel, textfield = Ext.form.TextField, etc. When you create a page or a form, you may use these xtypes rather than instantiate objects. For example,
items: [{
xtype: 'textfield',
autoWidth: true,
fieldLabel: 'something'
}]
Moreover, creating pages in this manner allows Ext JS to render lazily the page. This is where you see a "performance gain." Instead of creating a large number of components when the app loads, Ext JS renders components when the user needs to see them. Not a big deal if you have one page, but if you exploit tabs or an accordion, many pages are initially hidden and therefore the app will load more quickly.
Furthermore, you may create and register new components creating xtypes of your choosing. Ext JS will similarly render your components lazily.
You may also retrieve components by ID. Since your component (as well as the Ext JS components) may provide a bunch of nice behavior, it is sometimes convenient to search for and retrieve a component rather than a simple DOM element or node.
In short, xtypes identify components and components are a key aspect of Ext JS.
I'm new to Sencha/Ext JS but I think at this point the odd notion of having a shorthand definition identifier string for only UI components must be to satisfy legacy users.
Look at the "List of xtypes" here: http://docs.sencha.com/touch/2-0/#!/guide/components
Is there any good reason to use a similar-but-not-quite-the-same string identifier as the "class" name as the shorthand definition identifier? I don't think so.
Check the following sample of some xtype to class name mappings for Sencha touch:
video - Ext.Video Ok this sort of makes sense - lowercase version of 'class' name
carousel - Ext.carousel.Carousel Same pattern here
carouselindicator - Ext.carousel.Indicator Um, ok - we'll include a package too
navigationview - Ext.navigation.View And again here
datepicker - Ext.picker.Date Ok, wtf?
Some of the arguments above for xtype were that it allowed deferred instantiation of components. I think that is completely irrelevant - what allows deferred instantiation is the fact that Sencha/Ext JS supports the specification of a string identifier in place of an instantiated component in a view hierarchy.
The mapping of a particular string to a particular component that might be instantiated later is completely arbitrary - and in the case of Sencha/Ext JS, unfortunately silly (see examples above).
At least just follow a sensible pattern - for example why couldn't a Ext.Label have an "xtype" of Label? Too simple?
In reality I know why - it's because they made xtype names that read well - there are many repeated class names that wouldn't work (Ext.Panel and Ext.tab.Panel), and pickerDate would just sound stupid.
But I still don't like it - it's an odd little inconsistent shortcut that obfuscates more than it helps.
I asked the same question as Joe, but I found the answer. If you use xtype, one approach is to also specify an itemId in the same object:
{
itemId: 'myObject',
xtype: 'myClass'
...
}
Then you can find it with getComponent() as in
this.getComponent('myObject');
If you declare a class and give it an xtype, you can query it later with Ext.ComponentQuery.query()
For example:
Ext.create('MyApp.view.MyButton', {
xtype: 'mybutton',
.....
});
Later in your code, if you do:
var buttonArray = Ext.ComponentQuery.query('mybutton');
then buttonArray will contain an array of components of that class type. If you create components inline, your component query will be more complex.
Another advantage of xtypes is that if you move your classes around (let's say, you add another subdirectory under "view": MyApp.view.button.MyButton), then your component queries can still remain the same, since your xtype doesn't change. Once your project gets large, you will start creating subdirectories and moving classes around.
An xtype is simply a name given to represent a class. It is a
definition object which don't need to be instantiated when used in
any part of application.
While registering a xtype, we simply use this syntax: Ext.reg(<xtype name>,<classname>). But, we don't use the new keyword with the class name because the Component Mgr will automatically create instance of this class only if needed eg. in response to an event like click.
We don't need to get an instance manually because after registering an xtype, the 'Component Mgr' will automatically create an instance for the class represtented by that xtype only if it is used anywhere in the application or it simply don't instantiate that class if not used elsewhere. Component Mgr runs this code:
create : function(config, defaultType){
return new types[config.xtype || defaultType](config);
}
xtype don't instantiate the class when Ext.Ready runs. But, new Ext.Container() will create all instances when Ext.Ready runs. So, using xtype is intelligent for large applications to get rid of garbage objects.

Resources