Skip to content

Instantly share code, notes, and snippets.

@MichalBryxi
Last active July 20, 2021 19:02
Show Gist options
  • Save MichalBryxi/c33ff9ab9a95454d651d6927e94090fc to your computer and use it in GitHub Desktop.
Save MichalBryxi/c33ff9ab9a95454d651d6927e94090fc to your computer and use it in GitHub Desktop.
dynamic changeset
import Controller from '@ember/controller';
export default class ApplicationController extends Controller {
appName = 'Ember Twiddle';
}
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import {
validatePresence,
validateLength,
validateConfirmation,
validateFormat
} from 'ember-changeset-validations/validators';
import lookupValidator from 'ember-changeset-validations';
import Changeset from 'ember-changeset';
class MyValidations {
async validate(key, newValue, oldValue, changes, content) {
console.log('Spawning XHR validation');
try {
// Some XHR stuff goes here
// TODO[1]: This XHR call knows how to validate _every_ field. So ideally
// we want to call it only _once_ per change and then grab the results
// for every field in the form that uses this validator
return 'Server says no!';
} catch (_) {
return 'Server says double no!';
}
}
}
export default class extends Component {
@tracked changeset;
@tracked
fields = {
name: 'my name',
permissions: 'admin',
'field[0]_value': 'foo'
}
constructor() {
super(...arguments);
const ServerValidations = new MyValidations();
const AllValidations = {
name: [
validatePresence(true),
validateLength({ min: 12 }),
ServerValidations
],
permissions: [
validatePresence(true),
validateLength({ min: 12 }),
ServerValidations
],
['field[0]_value']: [ // TODO[3]: We are actually using indexes `field[0].value`, but that breaks changeset
validatePresence(true),
validateLength({ min: 12 }),
ServerValidations
]
};
// TODO[2]: This is not very dynamic. Once we add more fields to the form
// via "add field" button, we won't get our changeset updated
this.changeset = new Changeset(
this.fields,
lookupValidator(AllValidations),
AllValidations
);
}
@action addField() {
const oldLength = Object.keys(this.fields).length;
this.fields = {
...this.fields,
[`field[${oldLength}]_value`]: `new one ${oldLength}`
};
}
@action submitForm() {
// TODO[4]: No idea why, but validation works only once. If I click on
// "validate me now" for second time, the validation goes blank.
this.changeset.validate();
}
}
<form>
{{#each-in this.fields as |field value|}}
{{log this.changeset}}
{{#let (get this.changeset field) as |ch|}}
<label class="block text-gray-700 text-sm font-bold my-2">
{{field}}:
<Input
class="bg-white shadow-md border-2 rounded px-2 py-2 mb-4"
type="text"
name={{field}}
@value={{ch}}
/>
<ul class="text-red-500">
{{#let (get (get this.changeset.error field) "validation") as |errors|}}
{{#each errors as |error|}}
<li>
{{error}}
</li>
{{/each}}
{{/let}}
</ul>
</label>
{{/let}}
{{/each-in}}
<button
type="button"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
{{on "click" this.submitForm}}
>
Validate me now
</button>
<button
class="bg-gray-200 hover:bg-gray-400 text-black font-bold py-2 px-4 rounded"
type="button"
{{on "click" this.addField}}
>
Add field
</button>
</form>
<p class="p-4">
Once the user clicks on "Validate me now" the app sends (ideally) one XHR to the
server and checks for <em>all</em> the fields and their values. By clicking on
"Add field" user can add arbitrary number of fields and all those fields
will be validated with said XHR request.
In theory the client-side validation is optional. We were hoping to get both
of them going, but :shrug:.
</p>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<div class="container mx-auto px-4">
<Form />
</div>
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0",
"ember-changeset-validations": "3.14.7"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment