I'm looking at an older project that is using ExtJS. Admittedly, I'm not too familiar with this framework so I learn as I go and as I am asked to fix things. My issue is that there is a grid and each column uses allowBlank: false. This causes a tooltip box to display with some info about what field(s) need to be populated. This all works great, but I am trying to change that text in that tooltip i.e. "Error", "Benefit Category Name: This field is required", and I can't seem to make this work. How can I target and change that text? I'll include a screenshot of the grid and tooptip that I am talking about for reference. I am also using ExtJS version 6.
Here is a sample of one of the grid columns:
columns: [
{
dataIndex: 'benefit_category_name',
text: 'Benefit Category Name',
flex: 1,
editor: {
xtype: 'combo',
store: new Ext.data.ArrayStore({
fields: [
'benefit_category_id',
'benefit_category_name',
],
data: [],
}),
queryMode: 'local',
valueField: 'benefit_category_name',
displayField: 'benefit_category_name',
emptyText: 'Select one',
listeners: {
select: 'handleComboChange',
},
itemId: 'benefit_category_id',
allowBlank: false,
listeners: {
renderer: function(value, metaData) {
metaData.tdAttr = Ext.String.format('data-qtip="{0}"', value);
return value;
}
}
}
},
{
...
}
]
I tried to use the metaData property I read about in some other posts, but I can't seem to change the tooptip text (Error, Benefit Category Name: This field is required).
Here is a screenshot of the tooltip mentioned. I know this is an older framework, but any tips I could get would be useful. Thanks for your time.
Thats a simple validation example with custom message.
Ext.create({
xtype: 'textfield',
allowBlank:false, // will show required message - remove key to display vtypeText only
validateBlank: true,
vtype: 'alpha', // check for available types or create / extend one
vtypeText: 'Please change to what you want ...',
renderTo: Ext.getBody()
})
Details:
https://docs.sencha.com/extjs/6.5.3/classic/Ext.form.field.VTypes.html
https://fiddle.sencha.com/fiddle/3770
Related
I have an example fiddle in which I use Ext.window.Window to edit the grid entries.
The id of the value is displayed in the grid itself, and empty in the edit window.
For combobox in the grid, I did this and it works
{
text : 'type',
dataIndex : 'type',
flex: 1,
renderer: function (v, p, record) {
return record.get('type');
},
},
For combobox in the form edit I added to the combobox listeners:{ render: function(combo)}
{
xtype: 'combobox',
store: {
type: 'type-store'
},
fieldLabel: 'Type',
displayField: 'name',
valueField: 'id',
queryMode: 'remote',
publishes: 'name',
name: 'name',
listeners:{
'render': function(combo){
console.log(combo);
combo.setValue();//How set current value
}
}
But I do not understand how to correctly set the current value?
thank
First things first, in order to link the value of the combo, your data data.json you must include the id for the "type", not just the description:
{
"id": 1, "id_type":3 , "type": "Третий", "mytextfield": "Текстовое значение"
},
You can actualy use the "name" if you want to, but you have to change your combo valueField to "name" also.
In the controller, first load the combo store (or autoload) and then, instead using the view_model of the windows, use the form to load your record:
console.log(wind.lookup("mycombo").getStore().load());
wind.down('form').loadRecord(record);
I modified your fiddle with those changes
I am working in a sencha touch ap and I need to generate views with dynamic forms.
Configuration comes from the backend (JSON) and depending of this I paint a component or other.. for example:
"auxiliaryGroups": [
{
"id": "1000",
"name": "Basic Data",
"fields": [
{
"id": "1001",
"name": "Company name",
"editable": true,
"mandatory": true,
"calculation": true,
"internalType": "T",
"type": "textfield",
"options": []
}
]
}
],
Where type is related xtype in Sencha.
In the view I am creating all options of fields:
{
xtype : 'fieldset',
itemId: 'auxiliaryFieldsGroup3',
title: 'Requirements',
//cls : 'headerField',
items:[
{
xtype: 'togglefield',
name: 'f6',
label: 'Auxiliary field R1'
},
{
xtype: 'selectfield',
name: 'f10',
label: 'Auxiliary field R5',
placeHolder: 'Select one..',
options: [
{text: 'First Option', value: 'first'},
{text: 'Second Option', value: 'second'},
{text: 'Third Option', value: 'third'}
]
},
{
xtype: 'textfield'
}
]
}
And I receive the configuration from the server, I understand the view like a store of different fields, and from the controller, it should add only fields specified in the json object.
How to create this dynamically following MVC concept?
Thank you
I assume that you have all the fields in the auxiliaryGroups.fields array.
After loading the form data from AJAX you can do it like this in your success call.
succses:function(response){
var response = Ext.decode(response.responseText);
var fields = response.auxiliaryGroups.fields;
var form = Ext.create("Ext.form.Panel",{
// here your form configuration.
cls:"xyz"
});
Ext.Array.forEach(fields,function(field){
var formField = {
xtype: field.type,
label: field.name,
name: field.id
};
form.add(formField);
});
Ext.Viewport.add(form);
form.show();
}
Based on my comment on your question, my idea about dynamic form generation is using ExtJS syntax to load form definition would be something like the code below; of course it would be extended and the data can be loaded from the server.
Ext.require([
'Ext.form.*'
]);
Ext.onReady(function() {
var data = [{
fieldLabel: 'First Name',
name: 'first',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'last'
}, {
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype: 'email'
}, {
xtype: 'timefield',
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
}];
var form = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Simple Form',
bodyStyle: 'padding:5px 5px 0',
width: 350,
fieldDefaults: {
msgTarget: 'side',
labelWidth: 75
},
defaultType: 'textfield',
defaults: {
anchor: '100%'
}
});
form.add(data);
form.render(document.body);
});
update:
When you create a view in run-time, communication between view and controller might be problematic because the controller doesn't know anything about the view. considering that the controller is responsible for initializing the view with appropriate data and handling view's events, data binding mechanism in ExtJS can solve the first part (initializing the view) which is described at View Models and Data Binding, the second part (handling view's events) can be solved with general methods in the controller, every element in the view should send its event to some specific methods and the methods based on the parameters should decide what to do.
This approach makes your methods in the controller a little fat and complicated that is the price of having dynamic form.
It is worth to mention that EXTJS raises different events in the life cycle of controllers and views and you should take benefit of them to manage your dynamic form.
I don't know about Touch, but in ExtJS, I usually do it by using the add function of a fieldset. You just loop through all your records, and create the fields on the fly.
var field = Ext.create('Ext.form.field.Text'); //or Ext.form.field.Date or a number field, whatever your back end returns.
Then set correct config options on field then
formFieldset.add(field);
the below Ext JS code works fine. the combo box load the phone number properly when i edit the grid. But i need the text to display clear/delete with phone numbers in combobox. When i click clear/delete i need to add some functionality.
the combo box looks like looks like as follows:
Clear/Delete
121-224432133
123-344545353
666-323231231
423-4324442344
.
.
.
ExtJS code:
{ xtype: 'gridcolumn', header: 'Phone#', width: 100, dataIndex: 'PhoneNumber',
editor: {
xtype: 'combo',
typeAhead: true,
triggerAction: 'all',
selectOnTab: true,
store: App.mcmAllAgentsStore,
typeAhead: true,
emptyText : 'Clear/Delete',
displayField: 'PhoneNumber',
valueField: 'Agent',
queryMode: 'local',
listeners: {
scope: this,
specialkey: function(f, e) {
if(e.getKey() === e.ESC) { this.hide(); }
}
}
}
},
Maybe you should turn this boring combo box into a mighty GridPicker! Check the last example in particular.
Currently I'm working on an app that displays a chart of defects. The chart is to be filtered by a selection of checkboxes that the user can change around to fit his / her needs. These checkboxes are located in the gear menu of the app, under 'settings'. In App.js I have a function that looks like this:
getSettingsFields: function() {
return [
{
xtype: 'fieldcontainer',
fieldLabel: 'States',
defaultType: 'checkboxfield',
items: [
{...}
...
]
}
];
}
This function works perfectly so far and displays the items I left out of the code [they're not important to the question]. The problem is that now I want to add a ComboBox into the same settings page with custom values. The box should have the text [Days, Weeks, Months, Quarters] inside that will further filter which defects to display in the chart. I tried changing the getSettingsFields function to the following:
getSettingsFields: function() {
var myStore = Ext.create('Ext.data.Store', {
fields: ['value', 'range'],
data: [
{'value':'day', 'range':'Days'}, //test data for ComboBox
{'value':'week', 'range':'Weeks'}
]
});
return [
{
xtype: 'combobox',
fieldLabel: 'Date Range',
store: myStore,
displayField: 'range',
valueField: 'value'
},
{
xtype: 'fieldcontainer',
fieldLabel: 'States',
defaultType: 'checkboxfield',
items: [
{...}
...
]
}
];
}
Now when I run the app and click on the 'settings' button, everything disappears - even the field of checkboxes. Any explanation to why this is not working would be very helpful!
You're basically doing everything correctly- you've just stumbled upon a really subtle bug. The underlying issue is that there is an infinite recursion that occurs when the settings panel is attempting to clone the settings field config array due to the inclusion of the store. The following code will work around the issue:
{
xtype: 'rallycombobox',
storeConfig: {
fields: ['value', 'range'],
data: [
{'value':'day', 'range':'Days'}, //test data for ComboBox
{'value':'week', 'range':'Weeks'}
]
},
storeType: 'Ext.data.Store',
fieldLabel: 'Date Range',
displayField: 'range',
valueField: 'value'
}
It's basically the same as what you had but uses the rallycombobox instead and passes in storeType and storeConfig to get around the store cloning problem.
I want to be able to reorder the rows within a single grid. Im relatively new to extjs and have tried searching for this but all the resources i find are for older ext js versions and some of properties defined in those aren't valid anymore. eg- http://www.vinylfox.com/getting-started-with-grid-drag-drop/
xtype: 'grid',
id: 'row-grid',
hideHeaders: true,
store: 'SelectedRowStore',
//enableDragDrop: true,
//ddGroup: 'rowgrid-dd',
columns: [
{
header: 'Rows',
flex: 1,
sortable: false,
dataIndex: 'DisplayName'
},
{
id: 'button-column',
dataIndex: 'ID',
sortable: true,
hideable: false,
width: 35,
renderer: PA.common.RendererHelper.renderButtonForAddRowMainGrid
}
]
I'd really appreciate any help/advice on this issue.
Take a look at the grid to grid drag-n-drop example. It works with two grids, but I'm sure it can be easily modified to allow rearranging rows within one grid.
You can follow the sencha sample as Rene said or follow this:
Add this to your grid:
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
containerScroll: true,
dragGroup: 'someuniquenameforyourgrid',
dropGroup: 'someuniquenameforyourgrid'
},
},
And, only if you need some listener to do some anction, add (inside viewConfig):
listeners: {
drop: 'onDropGrid'
}
and event handler code in your controller:
onDropGrid: function (node, data, dropRec, dropPosition) {
...
}