Switch from textfield to displayfield with ExtJS4 - extjs

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)

Related

Duplicate reference when maximizing/restoring dialog

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)

How does an end user clear the sorting for a grid column?

I use ExtJs 6.6.0 Classic. The grid component supports multi-column sorting (I use remoteSort: true, remoteFilter: true). Whenever the user clicks on a column header, that column becomes the first column in the order by list. But I cannot find how an end user is supposed to clear the sorting for a column. The context menu available through the column header doesn't have a "Clear Sort" option.
See also this kitchensink example.
I feel like I am missing something. There is a sortClearText config for the column inherited from the header, but I could not find a place where it's used (I thought that perhaps there is some config I can use to add the Clear Sort menu item to the column context menu).
I could add a button to execute the action of clearing the sorting of the store, as a last resort, but I don't like it.
Is there a simple way to add a Clear Sort option for a grid column through the Extjs components configuration?
Thank you
I also did not find, but you can use the following override:
Ext.define('overrides.grid.header.Container', {
override: 'Ext.grid.header.Container',
getMenuItems: function() {
var me = this,
menuItems = [],
hideableColumns = me.enableColumnHide ? me.getColumnMenu(me) : null;
if (me.sortable) {
menuItems = [{
itemId: 'ascItem',
text: me.sortAscText,
iconCls: me.menuSortAscCls,
handler: me.onSortAscClick,
scope: me
}, {
itemId: 'descItem',
text: me.sortDescText,
iconCls: me.menuSortDescCls,
handler: me.onSortDescClick,
scope: me
}, {
itemId: 'dropSortItem',
text: me.sortClearText,
//iconCls: me.menuSortDescCls, // Your icon
handler: me.onSortClearClick,
scope: me
}];
}
if (hideableColumns && hideableColumns.length) {
if (me.sortable) {
menuItems.push({
itemId: 'columnItemSeparator',
xtype: 'menuseparator'
});
}
menuItems.push({
itemId: 'columnItem',
text: me.columnsText,
iconCls: me.menuColsIcon,
menu: hideableColumns,
hideOnClick: false
});
}
return menuItems;
},
onSortClearClick: function() {
var menu = this.getMenu(),
activeHeader = menu.activeHeader,
store = this.up('grid').getStore();
store.getSorters().each(function(sorter) {
if(sorter.initialConfig.property == activeHeader.dataIndex) {
store.getSorters().remove(sorter)
}
}, this);
}
});

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

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)

ExtJS: add button to htmleditor

I am using ExtJS and I have a htmleditor in my form. I would like to add a custom button to that element (for example after all other buttons like alignments, font weights, ...). This button should basically insert a standard template in the htmlfield. Being this template html, the behaviour of the button should be like this
Switch to HTML mode (like when pressing Source button)
Insert something
Switch back to WYSIWYG mode (like when pressing the Source button again)
Thanks for your attention
You don't need to switch to HTML mode. Just use the insertAtCursor function with the HTML template.
I made this easy example of how to add button which inserts a horizontal ruler (<hr> tag):
Ext.ns('Ext.ux.form.HtmlEditor');
Ext.ux.form.HtmlEditor.HR = Ext.extend(Ext.util.Observable, {
init: function(cmp){
this.cmp = cmp;
this.cmp.on('render', this.onRender, this);
},
onRender: function(){
this.cmp.getToolbar().addButton([{
iconCls: 'x-edit-bold', //your iconCls here
handler: function(){
this.cmp.insertAtCursor('<hr>');
},
scope: this,
tooltip: 'horizontal ruler',
overflowText: 'horizontal ruler'
}]);
}
});
Ext.preg('ux-htmleditor-hr', Ext.ux.form.HtmlEditor.HR);
Ext.QuickTips.init();
new Ext.Viewport({
layout: 'fit',
items: [{
xtype: 'htmleditor',
plugins: [new Ext.ux.form.HtmlEditor.HR()]
}]
});
You can see it running at: jsfiddle.net/protron/DCGRg/183/
But I really recommend you to check out HtmlEditor.Plugins (or ateodorescu/mzExt for ExtJS 4). There you can find a lot more about adding custom buttons, for instance, how to enable/disable the buttons when something is selected, put separators, etc.
You also can use ExtJS.ux.HtmlEditor.Plugins : https://github.com/VinylFox/ExtJS.ux.HtmlEditor.Plugins
In addition to #proton great answer above, there's another way to insert buttons to the toolbar, different from adding them to the end.
In my answer i'll write it as a new control named 'RichTextBox' (and not as a plugin) but this can be done in any other way:
Ext.define('Ext.ux.form.RichTextBox', {
extend: 'Ext.form.field.HtmlEditor',
xtype: 'richtextbox',
enableSourceEdit: false, // i choose to hide the option that shows html
initComponent: function () {
this.on('render', this.onRender, this);
this.callParent();
},
/**
* Insert buttons listed below to the html-editor at specific position.
* handler is implemented using 'execCommand':
* https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
*/
onRender: function () {
var me = this;
var tb = me.getToolbar();
var btns = {
StrikeThrough: {
//xtype: 'button', // button is default item for this toolbar
itemId: 'btnStrikeThrough',
iconCls: 'x-toolbar-strikethrough ', //choose icon with css class
enableOnSelection: true,
overflowText: 'StrikeThrough',
tooltip: {
title: 'StrikeThrough',
text: 'Toggles strikethrough on/off for the selection or at the insertion point'
},
handler: function () {
this.getDoc().execCommand('strikeThrough', false, null);
},
scope: this,
},
/** Seperator */
sep: "-"
};
tb.insert(5, btns.StrikeThrough); // insert button to the toolbar
//tb.insert(10, btns.sep); // add seperator
//tb.remove(26); // remove button, seperator, etc.
this.callParent(); //important: call regular 'onRender' here or at the start of the foo
}
});

Resources