PDA

View Full Version : How to replace placeholder components



froamer
7 Jul 2010, 9:24 AM
While we are waiting for Ext Designer to incorporate the ability to use custom components, you may find this override useful. It replaces a component (a place holder component for example) with another...

FOR EXTJS3...

/**
* Replaces a component with another, preserving the original config
* @param {Component} newComponent the new component to replace this one with
* @return {Component} this the replaced component
*/
Ext.override(Ext.Component, {
replaceWith : function(newComponent){
var ctnr = this.ownerCt;
// if the refOwner is a form or if newComponent.ownerForm config is set to the form
var form = newComponent.ownerForm ? newComponent.ownerForm : this.refOwner.form;
var i = ctnr.items.indexOf(this);
// apply initialConfig
Ext.applyIf(newComponent, this.initialConfig);
ctnr.remove(this, true);
var added = ctnr.insert(i, newComponent);
// if the component is in a form
if (form){
// remove the old component from the form
form.remove(this);
// add the new component to the form
form.add(added);
}
}
});


FOR EXTJS4 (Thanks JoelRSimpson)...


/**
* Replaces a component with another, preserving the original config
* @param {Component} newComponent the new component to replace this one with
* @return {Component} this the replaced component
*/
Ext.override(Ext.Component, {
replaceWith : function(newComponent){
var ctnr = this.ownerCt;
// if the Owner container is a form or if newComponent.ownerForm config is set to the form
var form = newComponent.ownerForm ? newComponent.ownerForm : this.ownerCt.form;
var i = ctnr.items.indexOf(this);
// apply initialConfig
Ext.applyIf(newComponent, this.initialConfig);
ctnr.remove(this, true);
var added = ctnr.insert(i, newComponent);
// if the component is in a form
if (form){
// remove the old component from the form
form.remove(this);
// add the new component to the form
form.add(added);
}
}
});

To use it, design your form in Ext Designer and add placeholder components where you want to include custom components. Give them an autoRef and export the project.

Paste the above override into a JavaScript file and load it in your page along with any custom component files needed.

In the subclass initComponent method you can then do something like this...

this.tagsField.replaceWith({
xtype:'superboxselect',
mode: 'local',
displayField: 'tag',
displayFieldTpl: '{tag}',
valueField: 'tag',
queryDelay: 0,
triggerAction: 'all'
});

In the example above my placeholder component had an autoRef of "tagsField" and I am replacing it with the rather groovy SuperBoxSelect custom component.

Note: thanks to Otávio's post below, the original config is preserved so you only need to specify the config needed by your new component.

oaugustus
8 Jul 2010, 2:52 AM
Great job guy,

It's very useful. I have a suggestion on replaceWith method:



replaceWith : function(newComponent){
var ctnr = this.ownerCt;

// if the refOwner is a form or if newComponent.ownerForm config is seted get the form
var form = newComponent.ownerForm ? newComponent.ownerForm : this.refOwner.form;

var i = ctnr.items.indexOf(this);

// apply initialConfig, thus not need rewrite config on "this.tagsField.replaceWith({xtype: 'superboxselect'})"
Ext.applyIf(newComponent, this.initialConfig);

ctnr.remove(this, true);
var added = ctnr.insert(i, newComponent);

// if the component is in a form
if (form){
// remove the old component to the form reference
form.remove(this);

// add the new component to the form reference to setValue work fine.
form.add(added);
}

}

Cheers, and thank you for sharing.

froamer
8 Jul 2010, 6:36 AM
Hi Otávio,

Many thanks for taking this to the next logical step, preservation of the original config is a great improvement. I have tested this in my code and it works well. I have adjusted my original post so people reading this will get your tweaks.

jarrednicholls
8 Jul 2010, 12:00 PM
Very nice froamer and Otávio. A great workaround for UX components!

skawaii
27 Jul 2010, 11:26 AM
Awesome! Just what I was looking for. Thanks!

wemerson.januario
27 Jul 2010, 5:04 PM
very nice Override.

htammen
12 Sep 2010, 2:59 AM
Inside a FormPanel this technique only seems to work if the component that replaces the placeholder has a clearInvalid() method. This is the case for all Field components and its subcomponents.

I tried to replace the placeholder with an Ext.Container that contains other field subcomponents and I´ve got the error "f.clearInvalid is not a function" for the container component. Also the replacement with a ReCaptcha component (see http://www.sencha.com/forum/showthread.php?34796-2.x-Ext.ux.reCAPTCHA-Form-Plugin) didn´t work. I had to add the clearInvalid() method to the ReCaptcha component.
If I replace the placeholder with a composite field everything works fine.

:-((

jarrednicholls
13 Sep 2010, 7:29 PM
I think the FormPanel will register all Field child items within itself when it's initializing. It uses that enumeration of Fields for rolling through validations, etc. You can put a placeholder of a Container and should be able to replace it with another Container no problem...if you use a Field placeholder, you're best off replacing it with another Field component.

fargs
27 Nov 2010, 6:40 AM
Hi,

I am having an issue with using the superselectbox ux in a component that was built using the Ext Designer.

I have used the replaceWith override and a textfield placeholder. I "link" my form component into my "Edit existing item" page and I have a window that uses another "linked" form for my "New" page. Pretty straight forward.

The edit page gets rendered first. When I click the New button to show the New window, an additional control seem to be displayed on the edit form and 2 new labels are displayed on the new form but no control. This may be a bit confusing so I have included a link to some screenshots to help explain. (I tried linking them directly in the post but I couldn't them to show up)

The first screenshot is when the first page loads and the second is when the window is shown.

http://picasaweb.google.com/lesliefarago/SharedDevelopmentScreenshots

Thanks for you help!

jarrednicholls
29 Nov 2010, 9:32 AM
Hi fargs,

So you are using the same form inside of two different containers, correct? Are you using the same "instance" or creating a new instance of the form per Window? Doesn't it sound like the Window is using a different instance of the form. If you provide some code samples, I could probably pinpoint the issue.

Thanks,
Jarred

fargs
1 Dec 2010, 4:10 PM
Hi Jarred,

My form is a component created using the designer. I have another Window component that has the form "Linked" to it and the same form is "linked" to the a panel in my viewport. So I am creating to instances of the form I believe and from the generated code this appears to be true.



MyPanel29Ui = Ext.extend(Ext.Panel, {
region: 'center',
initComponent: function() {
this.items = [
{
ref: 'personform',
xtype: 'personform'
}
];
MyPanel29Ui.superclass.initComponent.call(this);
}
});


Thanks!

j-joey
1 Dec 2010, 4:48 PM
hi guys.

i have another problem, and couldn't find a way yet. i've got a textfield in my toolbar and i'm replacing it with a ux.searchfield. but after this, i cannot reach to searchfield by ref anymore.

any suggestion?

ssamayoa
2 Dec 2010, 4:02 PM
Im revisiting ExtJS for a new project and wondering the same... :(

How good is the hack?

Regards.

ssamayoa
7 Dec 2010, 6:05 AM
I just used and worked likea charm!

I hope we will not need this hack in the nearest future...

jerrel
21 Mar 2011, 4:20 PM
He Guys,

Indeed this is a great hack.
I tried it with the ux FileUploadfield, and my placeholder textfield (name:file-path) is nicely replaced with the fileuploadfield (buttononly:true)

everything works as expected, except when i put my placeholder in a toolbar (fbar)

My backend php script cant seem to find the filename.

when i trouble shoot this in firefox, is see the following (check pic) 25292
Any idea how to resolve this ?

wemerson.januario
9 Aug 2011, 5:13 AM
Did anyone make it for Ext. 4x, or Is There any native method now in Ext. 4.x?

JoelRSimpson
28 Sep 2011, 4:49 PM
It looks like refOwner is no longer supported so I've replaced it with ownerCt.



/**
* Replaces a component with another, preserving the original config
* @param {Component} newComponent the new component to replace this one with
* @return {Component} this the replaced component
*/
Ext.override(Ext.Component, {
replaceWith : function(newComponent){
var ctnr = this.ownerCt;
// if the Owner container is a form or if newComponent.ownerForm config is set to the form
var form = newComponent.ownerForm ? newComponent.ownerForm : this.ownerCt.form;
var i = ctnr.items.indexOf(this);
// apply initialConfig
Ext.applyIf(newComponent, this.initialConfig);
ctnr.remove(this, true);
var added = ctnr.insert(i, newComponent);
// if the component is in a form
if (form){
// remove the old component from the form
form.remove(this);
// add the new component to the form
form.add(added);
}
}
});

ssamayoa
28 Sep 2011, 4:56 PM
Thanks.

froamer
28 Sep 2011, 9:52 PM
Hi JoelRSimpson, I've updated my first post so people can easily find your ExtJS 4 fix. Many thanks!

ssamayoa
12 Oct 2011, 11:05 AM
Designer 1.2.1-27 hasnt autoRef property so to replace placeholder component, searchfield in my case, I have to get the component after callParent():



initComponent: function() {
var me = this;
var store = Ext.create("test.store.Customers");
me.bbar = {
xtype : "pagingtoolbar",
store : store,
displayInfo : true
}
me.store = store;
me.callParent(arguments);
me.down("[name=buscar]").replaceWith({
xtype : "searchfield",
store : store
});
}


Is some better way to do this?

Thanks.

x10
7 Nov 2011, 5:41 AM
@"Update for ExtJS 4"
It doesn't work if i use ext-debug.js with dynamic loading
Ext.Loader.setConfig({enabled: true});
I get error

Uncaught TypeError: Cannot read property 'prototype' of undefined
in your
Ext.override(Ext.Component, { replaceWith ....?
It works only with ext-all.js

SOLVED: Define replaceWith in callback of Ext.require

Ext.require('Ext.Component', my_callback_with_definition_of_replaceWith);

ssamayoa
7 Nov 2011, 6:21 AM
@x10:

Did you include your component via "requires" in the Window or any other place such controller class?

Regards.

HyGy
30 Nov 2011, 6:33 AM
I try to use this overide with designer 1.2.2 and extjs 4.0.7

I created a form panel with designer, placed some form items on it, and a texfield as a placeholder, finally I give it an id.

I exported the project.

In the generated files initcomponent I call:


Ext.getCmp('paceholdertoreplace').replaceWith(
{
xtype: 'textareafield',
fieldLabel: 'Label',
anchor: '100%'
}
);


When I load the page, I got this in firebug:

form.remove is not a function

chrome://firebug/content/blank.gif form.remove(this);


I checked, and there is no a remove method in the form...

What I made wrong?

(Finally I want to replace it with xtype: 'itemselector' from the example ux.)

I searched autoRef parameter, but I can't found it in this designer version.

thanks,
HyGy

sbdi_dev
7 Dec 2011, 9:38 PM
great function. I'm using it with great success in Ext 3.4. Thanks

j.vreeken
17 Jan 2012, 2:47 AM
I try to use this overide with designer 1.2.2 and extjs 4.0.7

I created a form panel with designer, placed some form items on it, and a texfield as a placeholder, finally I give it an id.

I exported the project.

In the generated files initcomponent I call:


Ext.getCmp('paceholdertoreplace').replaceWith(
{
xtype: 'textareafield',
fieldLabel: 'Label',
anchor: '100%'
}
);


When I load the page, I got this in firebug:

form.remove is not a function

chrome://firebug/content/blank.gif form.remove(this);


I checked, and there is no a remove method in the form...

What I made wrong?

(Finally I want to replace it with xtype: 'itemselector' from the example ux.)

I searched autoRef parameter, but I can't found it in this designer version.

thanks,
HyGy

Commenting out the form part did the trick, i suppose this is not the best solution:


Ext.override(Ext.Component, { replaceWith : function(newComponent){
var ctnr = this.ownerCt;
// if the Owner container is a form or if newComponent.ownerForm config is set to the form
var form = newComponent.ownerForm ? newComponent.ownerForm : this.ownerCt.form;
var i = ctnr.items.indexOf(this);
// apply initialConfig
Ext.applyIf(newComponent, this.initialConfig);
ctnr.remove(this, true);
var added = ctnr.insert(i, newComponent);




/*
// if the component is in a form
if (form){
// remove the old component from the form


form.remove(this);
// add the new component to the form
form.add(added);
}
*/

after that i did a very simple replaceWith, nothing fancy, just replacing the textfield "tagsField" to a datefield and setting a new label:


/* * File: app/view/MyForm1.js
* Date: Tue Jan 17 2012 11:37:50 GMT+0100 (W. Europe Standard Time)
*
* This file was generated by Ext Designer version 1.2.2.
* http://www.sencha.com/products/designer/
*
* This file will be generated the first time you export.
*
* You should implement event handling and custom methods in this
* class.
*/


Ext.define('MyApp.view.MyForm1', {
extend: 'MyApp.view.ui.MyForm1',


initComponent: function() {
var me = this;
me.callParent(arguments);

Ext.getCmp('tagsField').replaceWith({
xtype:'datefield',
fieldLabel: 'Replaced textfield with datefield'
});
}
});

My goal is to use this override for placing a grid filter ux in a grid panel using Designer 1.2.2/ ExtJS4. So far, no luck.

I'm relatively new to all of this. Could someone give me some pointers / examples for achieving this?