Duplicate reference when maximizing/restoring dialog - extjs

When maximizing/restoring a dialog that contains some form fields with names, like:
Ext.create('Ext.Dialog', {
maximizable: true,
items: {
xtype: 'textfield',
name: 'id',
bind: '{record.id}'
},
buttons: [{
text: 'Save',
bind: {
disabled: '{!record.valid}'
}
}]
}).show();
we're getting an error:
Ext.mixin.Container.attachNameRef(): Duplicate name: "id" on ext-viewport between ext-textfield-1 and ext-textfield-5

Two found workarounds :
Disable animation
Ext.define('Override.Dialog', {
override: 'Ext.Dialog',
config: {
maximizeAnimation: false,
restoreAnimation: false
}
});
Make the proxy used for animation have no items (nor buttons since button disable state may not reflect the bounded value
Ext.define('Override.Dialog', {
override: 'Ext.Dialog',
config: {
maximizeProxy: {
items: null,
buttons: null
}
}
});

Background Information
During maximize and minimize ExtJS creates a shadow clone.
This will create a clone of the window, while you still have the original item.
Using an ID means, there can only be one identical one at any given time.
The clone tries to create the your textfield with the same ID, which does not work.
Typically you want to
for forms you usually do not need to grab each item as you can work with validator and getValues on the form
otherwise you might want to work with references in the view and lookupReference in the controller.
not use animation (because that does not create a clone)
write your own maximize animation and do the animation part yourself (write your own maximize function)

Related

ExtJS: Show/hide control on checkbox selectionchange

I have an ExtJS check-tree ExtJS Check Tree that I am trying to add some control to based on items checked/unchecked. It doesn't seem to fire correctly though.
Here is a Fiddle Example
When checkbox 'A' is selected, I want to hide the textfield, 'testValue', which works, but then if I unselect checkbox 'A', I want to show the textfield, 'testValue', which does not work.
For this test I am merely looking to see if the selections.selected.length === 0. However, when I unselect any of the checkboxes, the listener does not seem to be firing, since the alert message is not getting triggered - plus, if I then try to reselect the check box again it still does not fire.
I would use a selection Model (as outlined below) to achieve this (since I know it works), but then this places checkboxes on all my tree items when I just want to have the leaf nodes with checkboxes.
selModel: {
type: 'checkboxmodel',
listeners: {
selectionchange: 'onCheckedNodesChange'
}
}
Any suggestions would be most welcome!
EDIT
Adding allowDeselect: true and a listener for select and deselect sort of worked (I updated the Fiddle to exhibit the behavior):
selModel: {
allowDeselect: true,
listeners: {
deselect: function(model, record, index) {
text = record.get('text');
alert(text);
},
select: function(model, record, index) {
text = record.get('text');
alert(text);
}
}
},
I want to make sure that when 'A' is selected, the textfield remains hidden, but if you select another item in the list and then deselect it, the textfield returns.
I am trying to use the getChecked() method alone with when selectionchange event occurs. However, this only seems to return data when I do a submit (for example, on the Get checked nodes control). Any suggestions would be most welcome. This should not be so difficult.
For tree panel we have checkchange event it is similar to the selectionchange event.
http://docs.sencha.com/extjs/4.2.5/#!/api/Ext.tree.Panel-event-checkchange
checkchange( node, checked, eOpts )
Fires when a node with a checkbox's checked property changes
Parameters
node : Ext.data.TreeModel
The node who's checked property was changed.
checked : Boolean
The node's new checked state
eOpts : Object
The options object passed to Ext.util.Observable.addListener.
var fields = [
{
name: 'column'
},
{
name: 'leaf',
type: 'boolean'
},
{
name: 'checked',
type: 'boolean'
},
{
name: 'cls',
type: 'string',
defaultValue: 'x-tree-noicon'
},
];
this.dataModel = Ext.define('Filter-' + this.getId(), {
extend: 'Ext.data.Model',
fields: fields,
});
columns: [
{
xtype: 'treecolumn',
width: 200,
itemId: "filter",
dataIndex: 'column' ,
renderer: function (val, metaData, r) {
},
scope: this,
},
],
listeners: {
'checkchange': Ext.bind(function (node, checked,eOpts) {
},
scope: this
The checkboxes you are seeing are not part of the selection behaviour. Instead, they come from the checked configuration on the NodeInterface class.
Your tree panel is using the default selModel, which is row-based selection, with no deselect option. If you want the in-tree checks to control the selection, you'll need to configure that manually, probably by listening to change events from the store.
OTH, if all you care about is finding out which items are checked or not, you can use the getChecked() method on the TreePanel

Updating and rerendering components in ExtJS 4.2

Is there a way to re-render components upon tab switch? I have this data that loads all its store, which contains specific permissions. Each tab must only contain what was provided for their view. See my screenshot below:
Basically, this loads upon initComponent. The dilemma I'm currently having is that the Backoffice tab has a different permission with the Wombat tab. The idea is when either of them contains a permission say an Edit permission (sCreate), only that role is allowed to show the edit buttons as seen. So Backoffice has sEcommCreate while Wombat has sCreate. When either of them satisfies to true, it simply adds/pushes it to the column to be displayed during initComponent.
if (EcommBackoffice.plugin.Security.getAccess(oMe.sCreatePermission)) {
aColumns.push({
header: 'Action',
xtype: 'actioncolumn',
itemId: 'edit-role-btn',
width: 100,
sortable: false,
resizable: false,
draggable: false,
menuDisabled: true,
items: [{
icon: 'resources/img/editpermissions.png',
tooltip: 'Edit Permissions',
scope: oMe
}],
editor: {
xtype: 'text',
name: 'editRow',
cls: 'banks-delete-row'
}
});
}
How do I filter out the display upon switching on the other tab, and also on load? Currently, once sCreate or sEcommCreate passes its condition, it just adds the buttons on both roles since this is one single store.
Already tried reloading the data store from the controller, but it
only loads the data, and not rerender the components to either
add/remove/show/hide them.
To be more clear, I need to hide/remove the Action column if it has no create permissions assigned to it.
The actioncolumn and all actioncolumn items have a function isDisabled. I would recommend to use that function to enable/disabled the item, e.g.
items: [{
icon: 'resources/img/editpermissions.png',
tooltip: 'Edit Permissions',
isDisabled:function() {
var isWombatTab = (this.up('tabpanel').getActiveTab().text == 'Wombat');
if(isWombatTab) return EcommBackoffice.plugin.Security.getAccess(oMe.sCreatePermission)
else return EcommBackoffice.plugin.Security.getAccess(oMe.sEcommCreatePermission)
},
scope: oMe
}],
isDisabled() will be processed during grid refresh, so whenever you reload the store, the changes should come into effect. To force a refresh without changes to the store, you could of course call grid.refresh() from the activate event of the tabs.
It should then possible to hide the disabled item via CSS. I don't know exactly what it will take (may also depend e.g. on the theme you use), but a first guess is
.x-grid-cell-edit-role-btn .x-item-disabled {
visibility:hidden;
}

Blur/Click on Formpanel ExtJS 4 does not access form fields correctly

I have an ExtJS Formpanel and I have written a listener on a click for the form ( not on any fields of a form ) which is working fine.
Even after setting the Ext.FocusManager.Enable() to true, I am not able to get the even 'blur' working. What am I missing?
I am not able to access form fields from the event handlers for formpanel click event. When I do - this.up.('form').get.(fielname).value [which works fine in the event handlers on the form fields.] It says the element is undefined. How can I access the form elements here?
Adding the code snippet -
// Call it Object A
Ext.create.('Ext.form.Panel', {
id : xyz,
items: [
{
xtype : 'textfield',
name : 'test',
fieldLabel : 'Name'
}
listeners : { // listener on the formPanel; not on any of its element
click : {
console.log("this works" );
},
focus : {
console.log('this does not work');
}
}
]
}
I am doing this so that I can access a value of another object, say B.field.
Onload I am able to fetch the value of B.field. But when the user changes the value of B.field which is on a different tab, I am not able to fetch the changed value of B.field in A. I am just finding ways to avoid an Ajax call to the database, if possible.
Thanks in advance for your time.
Without any sample from your code to reference, it's hard to determine what you are trying to do.
It could be that you just need to fix how you are querying for the form elements. For example, elements in a toolbar are not children of the form, so up/down doesn't work.
I don't think you can listen for the events focus, blur, or click on a form. Even if you could, I am not sure you would want to do. Instead, it's more common to listen for focus on a field or click on a button.
Example 1 form with field using focus and button using click
http://codepen.io/anon/pen/qEPRge?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var form = new Ext.create("Ext.form.Panel", {
title: "person"
,items: [
{itemId: "fld-id", fieldLabel: "id", name: "id", value: "1", xtype: "textfield", labelAlign: "top", labelSeparator: ""}
,{itemId: "fld-name", fieldLabel: "name", name: "name", value: "Emily", xtype: "textfield", labelAlign: "top", labelSeparator: ""}
,{itemId: "btn-submit", text: "submit", xtype: "button"}
]
})
form.on("afterrender", function(component) {
console.log("form.afterrender")
})
form.render(Ext.getBody())
form.queryById("fld-id").on("focus", function(component) {
console.log("fld-id.focus")
})
form.queryById("fld-name").on("focus", function(component) {
console.log("fld-name.focus")
})
form.queryById("btn-submit").on("click", function(component) {
console.log("btn-submit.click")
console.log("fld-id.value:")
console.log(component.up("form").queryById("fld-id").getValue())
console.log("fld-name.value:")
console.log(component.up("form").queryById("fld-name").getValue())
})
})
})(Ext)

How to get an element in a View from a Controller?

I am using Sencha Touch 2,0,1.
I need to get an element from a View in a Controller.
At the moment I use this method, which get the View correctly, but I am not able to get the Item in the View. I do not get any error just test is undefined.
Any ideas?
In the Controller:
var test = this.getDetailView().items['editButton'];
Code in the View:
Ext.define('XXX.view.DetailView',{
...
items: [
{
xtype: 'button',
text: 'Edit XXX',
ui: 'custom-btn-dwn-timetable',
itemId: 'editButton'
}
],
...
}
There are a couple other ways to get the reference to the edit button. You can wire the edit button as a ref like this:
Ext.define('MyApp.Controller', {
extend: 'Ext.app.Controller',
config: {
refs: {
editButton: '#editButton'
}
},
Then in your controller you can call the automatically generated getterthis.getEditButton() to get the actual edit button component.
Another thing you can do is save the edit button as an instance variable on your view like this:
Ext.define('XXX.view.DetailView',{
...
items: [
this.editButton = Ext.widget{(
xtype: 'button',
text: 'Edit XXX',
ui: 'custom-btn-dwn-timetable',
itemId: 'editButton'
)}
],
...
}
So now to access your button in the controller you have to do: this.getDetailView().editButton
In general, if an element is something you access a lot you should have a saved reference to it, rather than querying the DOM (to avoid unnecessary performance hit). Using Ext.getCmp() is also slower due to execution stack (it has to go through the ComponentManager every single time just to get the reference).
You can use Ext.ComponentQuery in this case to get your button:
Ext.ComponentQuery.query('#editButton')[1];
You could try setting your button id to edit and then
Ext.getCmp('edit').hide();

Switch from textfield to displayfield with ExtJS4

I have created a form that displays values in plain displayfields.
There is an "edit" button next to the form and once clicked by the user, the displayfields should switch to being textfields and will, therefore, make the data editable.
This, I am guessing, would be achieved by having two identical forms, one editable and one not and one or the other would be visible, based on the user having clicked the button. Another way, perhaps, is to have the xtype dynamically selected upon clicking the button.
Can anybody point me towards a certain direction in order to do this? I am a complete newbie to ExtJS and only just started learning ExtJS4.
Thank you in advance.
M.
Start by rendering all fields as input fields with disabled:true. Then use this for the Edit button handler:
...
form.getForm().getFields().each(function(field) {
field.setDisabled( false); //use this to enable/disable
// field.setVisible( true); use this to show/hide
}, form );//to use form in scope if needed
Ext.getCmp('yourfieldid').setFieldStyle('{color:black; border:0; background-color:yourcolor; background-image:none; padding-left:0}');
Ext.getCmp('yourfieldid').setReadOnly(true);
You can toggle based on a property isEditable. Then when you click the button you change the property and just remove and add the form. It makes it cleaner if you are switching back and forth.
Ext.define('E.view.profile.information.Form', {
extend: 'Ext.form.Panel',
xtype: 'form',
title: 'Form',
layout: 'fit',
initComponent: function () {
this.items = this.buildItems();
this.callParent();
},
buildItems: function () {
return [this.buildInvestmentPhilosophy()];
},
buildInvestmentPhilosophy: function () {
var field = {
name: 'investmentPhilosophy',
xtype: 'displayfield',
editableType: 'textarea',
grow: true,
maxLength: 6000,
value: '---',
renderer: E.Format.textFormatter
};
this.toggleEditingForForm(field);
return field;
},
toggleEditingForForm: function (form) {
if (this.isEditable) {
Ext.Array.each(form, this.configureFieldForEditing, this);
}
},
configureFieldForEditing: function (field) {
if (field.editableType) {
field.xtype = field.editableType;
}
}
});
You can also try to have two items : a displayfield and a textfield with the same data source and you could hide/show the right item with your button handler.
You should not have any CSS problems
(If you did not have CSS problems I would enjoy to see you code)

Resources