How do I include object in DataGrid or SimpleForm in react-admin? - react-admin

How do I render an object with another object in it? E.g. I have a user object which has a field baseProfile which all look like this:
User
Id: String
Name: String
Address: String
BaseProfile:
password: String
email: String
......
I can easily use a SimpleForm or DataGrid to show or edit the first layer of data, how to show or edit the child object?

All inputs and field accept a path with dots.
<TextInput type="password" source="BaseProfile.password" />
<TextInput type="email" source="BaseProfile.email" />

Related

Base Input hides text instead of showing it inside the field

I have downloaded this design kit for Vue.js.
The thing is that when I'm writing text in it, it views the text I wrote, but after I focus out from the field, the text is hidden and the placeholder is shown back, but I couldn't understand why it does that.
When I'm printing the value of the field after writing in it, I get the value that I wrote, but I simply cannot see it inside the field.
Here is the code I'm using:
<base-input class="input-group-alternative mb-3"
:placeholder="email"
addon-right-icon="ni ni-email-83"
v-model="emailVal"
required="true"
:dir="dir">
</base-input>
I'm passing the email parameter as "Email Address" and the dir parameter as "ltr".
Could you please help me understand why it doesn't keeps my input inside the field?
Apparently the problem was that I didn't declared emailVal in my data object.
I added it like this, and it worked:
export default {
data() {
return {
email: 'Email Address',
dir: 'ltr',
emailVal: ''
}
}
}

Because it does not make the dynamic change, v-mask, vuejs

I have the following input
<input
type="text"
:disabled="disabledMoney"
v-model="packageForm.crime.forgeryCrimeSelected"
v-mask="{alias: 'currency', digits:0, min:minMoney, max:maxMoney}"
autofocus
/>
to which I assign the property max:maxMoney of data ();
This input is shown based on a radio button, so when selecting the radio button the input appears and with its correct max value, but if I try to change the max value in a method, the change no longer applies
in the method I just do
change(){
this.maxMoney = 6000 // Assigning new max
}
But it does not apply and stays with its initial value
What you need to do is use a computed value. This will re calculate everytime there is a change in state with the values involved.
Here is some reading from the docs: https://v2.vuejs.org/v2/guide/computed.html
Hey based on your comment, I would do something like this:
<input
type="text"
:disabled="disabledMoney"
v-model="packageForm.crime.forgeryCrimeSelected"
v-mask="{alias: 'currency', digits:0, min:minMoney, max:maxMoneyComp }"
autofocus
/>
computed: { maxMoneyComp(){ return packageForm.crime.forgeryCrimeSelected == 10000 ? 10000:25000; } }

To create custom attribute on input html element in Aurelia

I want to create a custom attribute input-format
I can assign two values to the attribute that would enable me to clean the input string or to trim input string.
Like below:
For value clean:
Trying to achieve declaring as below
<input
type="text"
placeholder="enter text with illegal characters"
value.bind="dirtyString"
input-format= "format : clean"
/>
The above should result me with the below embedded into the input element:
<input
type="text"
placeholder="enter text with illegal characters"
value.bind="dirtyString | cleanString & updateTrigger:'blur'"
keypress.delegate="keypress($event)"
/>
Similarly for trim
<input
type="text"
placeholder="enter your name"
value.bind="Name"
input-format= "format : trim"
/>
should result in:
<input
type="text"
placeholder="enter your name"
value.bind="Name | trimString & updateTrigger:'blur'"
/>
where cleanString, trimString, are value converters and keypress function which are already declared as needed. I need help with creating custom attribute as I am not sure of getting the current value bound to an html input element and also reassigning that to have all the above value converters and a function.
Can anyone please help me on achieving this? Appreciate your input and help.
This is where I stand:
import * as au from "aurelia-framework";
#au.autoinject
#au.customAttribute("input-format")
export class InputFormat {
constructor(element: Element) {
this.element = element;
}
#au.bindable
format: string;
formatChanged(name: string, newValue: string, oldValue: string) {
// need to have case statements
switch(name){
case 'clean':
// to assign the relevant value converter and the 'value' is to be passed into
// this assigment should result something like below
// <input
// type="text"
// value.bind="Name | cleanString & updateTrigger:'blur'"
// keypress.delegate="keypress($event)"
// >
break;
case 'trim':
// to assign the relevant value converter the 'value' is to be passed into
// <input
// type="text"
// value.bind="Name | trimString"
// >
break;
default:
// to leave the assigment as is
break;
}
}
// the select list
element: Element;
val: any;
}
here is the link where I am trying to put things together:
sand box link

How do you properly clear Aurelia binding of a complex object?

Background: I'm trying to create a form using Aurelia. I have a person object that I would like to be able to fill in data for. If the user knows some identifying information about the person's family, they can enter it in an input and a select box will be displayed to allow the user to select the individual from that family for this particular form. The form will then fill in any information it knows about that individual into input fields allowing the user to overwrite any of the information if necessary. The form also allows them to clear the selected person if they want to choose another one.
Most of the functionality seems to work as expected, but when I try to allow the user to clear out the selected person, I'm seeing some behavior that I wouldn't have expected.
I have created a GistRun. The bottom pane is working as I would expect, after the user gets data, selects a person and then clears their selection, they are provided with the select element again. If you uncomment the input element, you will see that the user now has to click the clear action twice before they see the select element again. Why?
How can I update the application so that the user will only need to clear out the person once and the select box will appear again to allow the user to make another selection?
If you have an Aurelia application, you should be able to reproduce this by replacing the app.html with the following:
<template>
<select value.bind="val2" if.bind="opts2 && !val2">
<option repeat.for="opt of opts2" model.bind="opt">${opt.firstName}</option>
</select>
<div if.bind="!opts2 || val2">
<span>${val2.firstName}</span>
<button click.delegate="clearVal2()" if.bind="val2">Clear</button>
</div>
<button click.delegate="getOpts2()">Get</button>
<div>${val2.blah}</div>
<!--<input type="text" value.bind="val2.blah"/>-->
</template>
An the app.js with this:
export class App {
opts2;
val2;
getOpts2(){
this.opts2 = [
undefined,
{
blah: 1,
firstName: 'foo',
address: {
line1: '123 Main St.'
}
},
{
blah: 2,
firstName: 'bar',
address: {
line1: '456 Other Wy.'
}
}
];
}
clearVal2(){
this.val2 = null;
}
}
Any help would be greatly appreciated. Thanks!
UPDATE
If I put the input in a custom element and bind to that, things seem to work as expected. The values that I'm putting into my form though aren't in one location that I could utilize a custom element for. I have updated the Gist with an example.
How can I achieve the same functionality without the need for a custom element?
In all honesty I'm not sure why, but if you add if.bind="val2"on the input element, it clears the value and the select button returns.
<input type="text" if.bind="val2" value.bind="val2.blah"/>
Hope this (slightly) helps
Give that you are allowing the user to either select a value from the list or create a completely new entry, I would tend towards separating the value selected in the list and the data backing up the text boxes. Whenever the value of the select changes, I would set the value of the object backing the text boxes to the value of the select. The way I chose to do this in my sample code is to use the observable decorator on the value the select is bound to.
Here's an example: https://gist.run?id=e4b594eaa452b47d9b3984e7f9b04109
app.html
<template>
<div>
<select value.bind="val" if.bind="opts && !val">
<option repeat.for="opt of opts" model.bind="opt">${opt.firstName}</option>
</select>
<button click.delegate="getOpts()">Get</button>
</div>
<div if.bind="!opts || person">
<span>First Name: ${person.firstName}</span>
<button click.delegate="resetForm()" if.bind="val">Clear Selection</button>
</div>
Address: <input type="text" value.bind="person.address.line1" />
<hr />
val
<pre><code>
${toJSON(val)}
</code></pre>
person
<pre><code>
${toJSON(person)}
</code></pre>
</template>
app.js
import {observable} from 'aurelia-framework';
export class App {
#observable val = null;
person = {};
getOpts(){
this.opts = [
null,
{
blah: 1,
firstName: 'foo',
address: {
line1: '123 Main St.'
}
},
{
blah: 2,
firstName: 'bar',
address: {
line1: '456 Other Wy.'
}
}
];
}
valChanged() {
this.person = this.val;
console.log("set person");
}
resetForm(){
this.val = null;
console.log("reset val");
}
toJSON(value) {
if(!(value === false) && !value) {
return '';
}
return JSON.stringify(value);
}
}
You can see something interesting is happening when I reset the form. Aurelia is creating the properties necessary for bindings to person (namely person.address.line1 when we set person = null. But it doesn't create a firstName property, b/c that property isn't being bound until person stops being falsey.
Another option here is to simply use the with attribute to scope the input.
https://gist.run/?id=7b9d230f7d3c6dc8c13cefdd7be50c7f
<template>
<template with.bind="val.address">
<input value.bind="line1" />
</template>
</template>
Although I agree that mixing the logic of selections and inputs like that is probably not the best idea :)

simple html value for nested form

I'm using rails, and backbone with handlebars, and I have a nested form.
I am trying to create a user, and the user can supply a url.
So I have a user model and a url model
I thought I could do something like this
<form id="new_user">
<label name="username" >username</label>
<input type="text" name="username" />
<label name="url" >url</label>
<input type="text" class="nested urls_attributes" name="url" />
</form>
----------------------update -----------------------------------------
as this is something that will be seldomly used, I've updated my backbone view to create the correct json when I submit the form, so now on submit form, I create the first json, then add the nested object.
var form_json = MyApp.Helpers.Serialize_Form($('form#user_form inputs').not('.nested'));
form_json['urls_attributes']=MyApp.Helpers.Serialze_Form($('form#user_form inputs.nested'));
this creates the json in the format of
{username: "test", urls_attributes: {url:"http://test"}}
So when I pass that to my controller, I expected that the url would be created when the user is created.
Unfortunately, that doesn't seem to be happening, and I have no errors. The user gets created, but not the nested model of urls.
Any idea why this is happening?
-----------how I make the json----------------------
I convert my form into a json object with
serialize_objects: function(inputs){
//this takes form inputs and creates a json string of them
var o = {};
$.map(inputs, function(t) {
if (o[t.name] !== undefined) {
if (!o[t.name].push) {
o[t.name] = [o[t.name]];
}
o[t.name].push(t.value || '');
} else {
o[t.name] = t.value || '';
}
});
return o;
}
I can't use jquery serializeArray because I'm using jqMobi which doesn't implement serializeArray. But that shouldn't matter for this question.