Ext JS Forms at multiple depth - extjs

So in an Ext js View I have a form which can potentially contain fields and multiple forms inside it and those forms that are contain by main form can also contain forms and fields. there is no limitation of how deep will the last form be. When I submit I want to get a thing like this
main-form
{
key1: value1,
key2: value2,
form-l2
{
key-l2:value-l2,
form-l3
{
key-l3:value-l3,
...
}
}
}
as an object.

In HTML, form cannot contain another form and in ExtJS, even if we could somehow trick it, it wouldn't play well and I doubt is is worth the effort.
Better would be to have one bounding form in which you'd implement the tree-like UI plus some custom methods (or overrides of the existing methods) to return the nested json made of the field values.

Related

Is it true that "setAllValues" works only with one level of the nesting of the form? (By default in React-form)

As I see react-form has a very convenient feature for set all data into form, but only it does not work correctly, when rendering form with 'setAllValues', all fields must be filled with data, but this does not happen for second and next levels of nesting.
Just for example object with data which I have:
const FormData = {
field1: "field_1",
fieldsGroup1: {
field2: "field_2",
field3: "field_3"
},
field4: "field_4",
fieldsGroup2: {
field5: "field_5",
fieldsGroup3: {
field6: "field_6",
fieldsGroup4: {
field7: "field_7"
}
}
},
field8: "field_8"
};
In this topic I would like to make sure that currently 'setAllValues' works only with one level nesting of form by default.
I decided this issue the following way...
I using two component to render form with setting all data to all nested fields
Please take a look on my example (here ->https://codesandbox.io/s/pjo46r9xnm ) for fully understand my point.
... All seems to work well, but there is a question for the experts, is there another way to fill the form (setting all values from state/store/with other way) with all the nested fields withoout any additional components and use only API react-form, since I didn't found such case in documentation/internet/gitHub of Microsoft)/stackoverflow atc.
or my approch a single way for implementation such case )
Thank you to interest with my question.
You can try one of these:
https://www.npmjs.com/package/deepmerge in addition to react-form
or if it fit to your needs
https://github.com/erikras/redux-form

Form controller in marionette

So I have a form that appears on a few pages and contains a number of groups of inputs. Say group a, group b and group c. On some pages they might have a and b and on others the form contains b and c. Each group may require its own client side custom validation maybe executed from the form controller.
What is the best way to achieve this using backbone and marionette?
Conceptually, and i'm fairly new to both, I'd assume I'd need a FormController that is instantiated from a page specific Controller which also instantiates the group controllers that I need for that page. Any advice would be great.
TL;DR
To make this work you would create two objects per input group. One for its custom functions, and one for its events. In the form controller you'd _.extend the function objects of each input group with a base form view to get the custom functions into your new form view. Next you'd pass in your custom events objects into the constructor for the new form view, where a utility function of your basic view would add the new custom events to the basic form view events. Finally, you'd have to ensure that you have a template for that form that contains the correct input groups.
I should also mention that you can accomplish this with Marionette.LayoutViews and dynamic regions, in a possibly cleaner way (you could specify an atomic template for each input group), albeit with a lot more overhead.
The expanded explanation
I've been toying with this idea a bit. I've been thinking a lot lately about using Underscore _.extend() to plug-in stock functionality to different views. Your problem would be ideal for this solution. Here's a sample of how you'd implement it.
Including functionality
Say that your input group A had a validate function that did it's thing,
validateA: function () {
// custom validation routine
},
and a submit function to handle form submissions,
submitA: function () {
// custom submit routine
}
The first thing you do is package these functions inside an object:
groupA = {
validateA: function() {...},
submitA: function() {...}
}
You'd have as many function objects as you have input groups.
You'd also build a generic form view that would house common form functionality, and which would also serve as the basic view you'd use to render your form
var GenericForm = Backbone.Marionette.ItemView.extend({...});
In here you'll put all your baseline events and functions common to all forms.
Then, as you mentioned you'd set up a FormController that would plug in the custom functionality, like this,
var formController = function () {
callFormZ: function() {
var genericForm = new GenericForm({ groupEvents: [eventsA, eventsB] });
var formZ = _.extend(genericForm, groupA, groupB);
SomeRegion.show(formZ);
}
}
By using _.extend on your basic view and your two input groups you end up with a new view, formZ that is a composite of the two input groups. If you'd look inside it would have all the functionality of GenericForm plus
{
validateA: function () { ... },
submitA: function () { ... },
validateB: function () { ... },
submitB: function () { ... },
}
Events
At this point, though there is no way to bind any events to your custom functions.
You may have noticed in the callFormZ controller that I passed in an array in a property called groupEvents. These are the custom events for your input groups. They'd normally have the form
eventsA: {
'blur .groupA': 'validateA',
'click #groupA button': 'submitA'
}
Ideally, we would just use extend to merge your events the way we did your functions. But since we want to end up with just one events property in your view, we run into a problem. _.extend will overwrite all the events properties in your view object with the events property of the last object passed into _.extend. So to get around this problem we have to pass an array of custom events, one for each form group.
First, you'd create a config array of events objects with your custom events for the particular form you're working with,
customEvents = [
eventsA: {
'blur .groupA': 'validateA',
'click #groupA button': 'submitA'
},
eventsB: {
'blur .groupB': 'validateB',
'click #groupB button': 'submitBA'
}];
You'd pass this array into your constructor, as we did in the callFormZ controller function. The array will now be loaded in your options parameter. In your initialize you can call something like this,
initialize(options) {
combineEvents(options.groupEvents);
this.delegateEvents();
}
where, combinedEvents is
combineEvents: function() {
var extendEvents = [this.eventsA, this.eventB]; // Make an array of the extended groups
_.each(extendEvents, function (extendEvent) {
for (prop in extendEvent)
this.event[prop] = extendEvent[prop];
}
}
Also, note that after combining events I called delegateEvents so that we'd rewire the new events.
Templates
To make all this work you'll have to provide a template that has the portions of each input group. I'm not aware of how we construct the template programmatically from individual input group templates. Instead, you'd have to have a template with the input groups relevant to the form.
Putting it all together
So, to make this work you would create two objects per input group. One for its custom functions, and one for its events. In the form controller you'd _.extend the function objects of each input group with a base form view to get the custom functions into your new form view. Next you'd pass in your custom events objects into the constructor for the new form view, where a utility function of your basic view would add the new custom events to the basic form view events. Finally, you'd have to ensure that you have a template for that form that contains the correct input groups.

Drupal 7: How to draw all widgets for a node-add form dynamically

I'm working on a module in which I need to draw multiple node-add forms, from different content-types, in the same page and save them all at once. I have all the content types of every node I need to add, and I even managed to get the fields using field_info_instances("node", $type).
Now I need to render the fields. I found node_add() but this function creates the entire form, including save buttons and publishing options. I only need the widgets for the fields.
Is there a hook or a function in drupal that will render only the widgets for a node-add form given the content type, or even the widgets for a field given it's info?
R.
PS: I'm working on drupal 7.x
Calling node_add($content_type); will give you the node add form for this specific form type.
I'd think this way
$form = array();
$types = array('page', 'blog', 'article');
foreach ($types as $type) {
$type_form = node_add($type);
// Somehow merge this data with the $form array avoiding the conflicts
// resulting from mulitple fields with same name.
// and find a way to submit all of them with one button .. ajax?
}
return $form;

EXT.JS getting a list of items from a fieldset

How can I get a list of items from a Ext.form.Fieldset? I'm trying to find a component based on one of its properties, this is what I've got so far:
Ext.each(container.items, function (component) {
if (component.name == config.name) {
component.doUpdate(config);
}
}, me);
Of course, items is undefined...so what can I do to access the components contained in my container, which is a fieldset?
You can use container.down(selector) or if its a form field use form.findField(name).
See this answer on the different ways to 'find' things in an extjs app:
Testing extjs apps
For form fields here is an answer that lists different tricks: Best way to access adjacent components / fields
EDIT: Use container.query(selector) method to get an array of objects. As down() method returns first found.

how to create reusable and MCV-compatible form fields in extjs4?

I have some form fields and field sets and i want to reuse them in different views( Which may have different layouts and/or more fields).
I need a solution under which i dont have to repeat these form fields in every view i create and i want to reuse previously defined ones.What do you suggest for a MVC-based application?
Here is a very basic custom component that you can reuse in forms (it would go in your app/form/field folder with name InterestRate.js):
Ext.define('app.form.field.InterestRate', {
extend: 'Ext.form.field.Number',
alias:'widget.ratefield',
minValue:0,
step:0.05,
fieldLabel:'Rate'
});
You could then use it in a form like this:
Ext.define('app.view.Quote', {
extend:'Ext.form.Panel',
requires:[
'app.form.field.InterestRate'
],
items:[
{
xtype:'ratefield'
}
]
});
You can make the component as complex as you want, such as a whole grid or a fieldcontainer with multiple items.
The question is, do you want its behaviour to be self-contained, or to be controlled by the controller of the main form?

Resources