aurelia / validatejs

Enables expressive validation using decorators and/or a fluent API.
MIT License
22 stars 23 forks source link

Validation renderer gets an instance of a class, not the html element #63

Closed MaximBalaganskiy closed 8 years ago

MaximBalaganskiy commented 8 years ago

https://gist.run/?id=66e783f15c68f439adfee440d55438ca

As you can see I validate the md-value on a custom element. The renderer md-validation-renderer.js receives a parameter node which is an instance of an md-input class defined by the bridge. Luckily, it has an element field which I can use. But I cannot assume that all custom elements will expose an HTML element.

In a nutshell, I don't particularly like this code in the renderer

    if (node.element)
        this.renderErrorsOnElement(node.element, relevantErrors);
    else if (node.classList)
        this.renderErrorsOnElement(node, relevantErrors);
ggrimbert commented 8 years ago

Solved by this :

<div ref="parentElement">
YOUR CUSTOM ELEMENT
</div>

Doing this, the node passed gets a parentElement even if this is not an html component.

MaximBalaganskiy commented 8 years ago

Should this be added to an element template?

ggrimbert commented 8 years ago

This doesn't work with template, I cannot remember why... But you can add the div inside the template like this :

<template>
<div ref="parentElement">
[...]
</div>
</template>
MaximBalaganskiy commented 8 years ago

That's fine for my own controls. What about 3rd party controls like Materialize which might not have element or parentElement exposed?

ggrimbert commented 8 years ago

I haven't integrated this, so I can't help you

plwalters commented 8 years ago

@MaximBalaganskiy can you summarize the changes you are proposing or put together a PR?

MaximBalaganskiy commented 8 years ago

@PWKad I'm not that familiar with the framework to submit a PR, I'm afraid.

I think, renderer must have access to an HTML representing the custom element. Are there any framework services which can take a class instance and return a UI tree? If yes it can be injected into a renderer or binding behavior.

JeroenVinke commented 8 years ago

I have the same issue with the validate binding behavior on a custom element / attribute. Used the following code to reproduce:

<!-- md-input.html -->
<template>
  <input type="text" value.bind="mdValue"/ />
</template>
// md-input.js
import {bindable} from 'aurelia-framework';
export class MdInput {
  @bindable mdValue;
}
<div>
  <label class="form-group">
    <strong>First Name</strong>
    <!-- <input class="form-control" value.bind="model.firstName & validate" /> -->
    <md-input md-value.two-way="model.firstName & validate"></md-input>
  </label>
</div>

An assumtion is made here that binding.target is the HTML element, which is true for <input value.bind="model.firstName & validate"/> but when a custom element is used binding.target is the instance of the MdInput viewmodel

here is a Binding created with the viewModel as target. Unfortunately I can't find the <input/> anywhere else on the binding or source (https://github.com/aurelia/validatejs/blob/master/src/validate-binding-behavior.js#L11)

@jdanyow do you know of other ways to get the HTML element from a binding behavior?

JeroenVinke commented 8 years ago

if anyone is interested, I made a workaround: https://github.com/JeroenVinke/validatejs/commit/7876e9a4ec124cd8e510e4ba69fa7c452f1473c1

It is used like this: <md-input ref="_firstName" md-value.two-way="model.firstName & validate:_firstName"></md-input>

jspm install aurelia-validatejs=github:JeroenVinke/validatejs@master

jdanyow commented 8 years ago

this is fixed in the latest build