Complex calculated fields and values with react-final-form inside Edit - react-admin

I am developing a complex Edit form which includes over 200 fields, roughly half of them are calculated by using values from other fields, in some cases formulas refer to values from multiple other fields.
I am trying to use react-final-form's <Form\> inside react-admin's Edit. I cannot figure out how to reference more than one field in the decorator, for some reason allValues is only visible before "=>" in the update statement. It seems to be working fine outside of react-admin but not when integrated in the react-admin's Edit.
Object is possibly 'undefined'. TS2532
77 | field: ["Field1"],
78 | updates: {
> 79 | Field2: (Field1Value, allValues) => Field1Value + allValues.Field3 * 10
| ^
80 | }
81 | }
82 |
Another issue is that I cannot find a way to refer to the form's values, "values" prop is not populated when the Form is used inside of Edit.

you cannot use an array as a field value. the concept of react final form decorator is to find a change in any field and you can mutate other fields accordingly. That is the reason you cannot pass array as a field value.
{
field: 'product_code', // if product_code changes
updates: {
bill_amount: (product_code, allValues) => do some calculations,
total_discount: (product_code, allValues) => do some calculations
}
}
I also have some code example for you as I recently work with final form decorator

Related

Vuetify - strict datatable custom filter

So I have a data table whereby the names of the objects are similar and case sensitive like "A", "Aa", or "a" and I'm having issues trying to filter the data by those exact values. I'm filtering my data using a v-select bound to the search property of the data table. When creating the custom filter, the only two options I've found are by filtering the specific column by the search input:
customFilter(items, search, filter) {
search = search.toString().toLowerCase();
return items.filter(row => filter(row["name"], search));
}
or filtering the Object.keys:
customFilter(items, search, filter) {
search = search.toString().toLowerCase();
return items.filter(i => (
Object.keys(i).some(j => filter(i[j], search))
))
}
With how the custom filter works, I can't seem to use the search parameter without it being put to lower case as removing .toLowerCase() breaks it completely and using a different method on the Objects.key like .find() rather than .some() results still filters the "Aa" items when selecting "A" or "a".
Is there any way I can use the custom filter in order to filter my items both case sensitive and by the string exactly?
Thanks!
Turns out using the search and custom filter of the data table was the wrong way about it as they're too restricted. I just linked the datatable to a separate array which I filter myself when selecting an option in the v-select.

Yii: Compute custom field for model

I find the documentation and tutorial of Yii 2.0 a bit short.
In a Yii 2.0 Model I would like to add a hidden field with a computed value, let's call it def_id. The model contains fields such as firstname, lastname, email etc. The computed value would be some combination of those three fields. (It is supposed to be some custom type of the logical, unique auto-increment.)
My question: where do I compute def_id with the other given fields so that Create and Update will write def_id into the database-table?
There is no hidden field in the model, there are just fields. If it is calculated field you do not have to even show it on screen so there is no point in putting in a hidden field.
You can however add it to the before save function for the model
public function beforeSave()
{
if ($this->isNewRecord) {
//calculate what you need
} else {
//recalculate if needed
}
return parent::beforeSave();
}

sitecore mvc value of droplink

I am looking for the simplest way to get the referenced item value for a droplink field.
#Html.Sitecore().Field("Alignment")
I want to get the value of the choice, what's the best approach?
If you need to have ability to edit fields of alignment item which is chosen in 'Alignment' droplink field of context item or just show values of alignment item's fields for visitors:
#{
Sitecore.Data.Fields.ReferenceField alignmentField = Sitecore.Context.Item.Fields["Alignment"];
Sitecore.Data.Items.Item alignmentItem = alignmentField.TargetItem;
}
<div>
#Html.Sitecore().Field("Text of Alignment", alignmentItem)
</div>
This example assumes that Alignment template contains 'Text of Alignment' field.
The Droplink field stores the referenced item's ID. To retrieve this ID (providing the field is present in your current item/model):
((LinkField)Model.Item.Fields["Alignment"]).Value
To output the referenced item's name, you could do something like this:
#(Model.Item.Database.GetItem(((LinkField)Model.Item.Fields["Alignment"]).Value).Name)
But that's really ugly. The preferred approach would be to create an extension method encapsulating some of the above so you're not having to re-type that out :D
The article Extending the SitecoreHelper Class by John West shows how to extend the SitecoreHelper class to add custom field renderers, so you could end up creating a neat re-usable snippet like:
#(Html.Sitecore().ReferenceField("Alignment","Name"))
If this is in a partial view i.e. .cshtml file you can also use something like below:
Sitecore.Data.Fields.TextField alignment= Model.Item.Fields["Alignment"];
This will give you the id of the set item in the drop link , then from that id can retrieve it from the database like:
#if (!string.IsNullOrWhiteSpace(alignment.Value))
{
var setAlignment = Sitecore.Context.Database.GetItem(alignment.Value);
if (setAlignment != null && !string.IsNullOrWhiteSpace(setAlignment.Name))
{
setAlignment.Name
}
}
Personally i prefer this way as i can check if the droplink is set before trying to use the value.

searchAttr combobox array

I was wondering how could I have mutli-search Attr in my combobox. I would like to have someting like :
var cb = dijit.byId('myCombo');
cb.attr('store', store);
cb.attr('searchAttr', ["name","age"]);
So I can make autocomplete on two criterias.
I will assume you are using a dojo.data.ItemFileReadStore. The searchAttr is only for the attribute you're typing in the ComboBox.
For example, if you're typing a name, but you also want to filter by age, you add a field to the query parameter:
// Get names with age=30
// Use set because attr is deprecated
cb.set( 'query', { 'age' : 30 });
If you want to be more specific with a name when the page is initially loaded, you can specify it in your query:
// All names starting with 'a' and age=30
cb.set( 'query', { 'name' : 'a*', 'age' : 30 });
If you want your age to be dynamic, you must get it from another place (e.g. dijit, form element, dom node, etc.). Here is an example to get age from another dijit called 'anotherDijit' (a NumberTextBox for example) when the page loads:
// Get names with age specified in 'anotherDijit'
cb.set( 'query', { 'age' : dijit.byId('anotherDijit').getValue() } );
However, for the age value in the query to change when the 'anotherDijit' diijt changes, you have to do one of two things:
Attach an observer/event handler to an appropriate 'anotherDijit' event (e.g. onChange), which will update the new 'anotherDijit' value in your ComboBox store query. This is a PUSH approach.
Attach an observer/event handler to an appropriate ComboBox event (e.g. onFocus), which will PULL the current value from the 'anotherDijit' dijit, and then update the store query parameter.
Notice that the fields you put in 'query' parameter are queried like AND (name=this AND age=that, etc). If you need more complex queries, with ORs and NOTs, you can use dojox.data.AndOrReadStore, for example.

how to represent trees and their content in MySQL?

I need to be able to store something like this:
where the green is a template type, the gray is a field container type, and the white is field. (That being, a field has a label and some text, both mediumtext for simplicity; and a field container can store other field containers or text, and a template is a top-level field.)
Now, let's say I want to allow users to create any number of these structures, but it is unlikely to be more than say 10. And, of course, we need to be able to link data to it.
This is all to be able to store in a database an associative array that looks for the above like, in pseudo code:
my_template = {
page_info => { description => 'hello!!!' },
id => 0,
content => { background_url => '12121.jpg', text => ...
}
Having an easy way to add a field to all data using the template when the template changes (say, we add a keywords to page_info) would be a big plus.
I can't figure this out at all, thanks a lot!
There are several different ways to store heirarchical data structures (trees) in MySQL. You can for example choose:
Adjacency list
Nested sets
Path enumeration
Closure table
See Bill Karwin's presentation for more details on the pros and cons of each.