2017-01-19 8 views
2

Я пытаюсь использовать плагин aurelia-validation для выполнения проверки в форме. Я создаю настраиваемый рендерер проверки, который изменит цвет поля ввода, а также разместит значок рядом с полем. При щелчке или наведении значка появляется всплывающее сообщение, отображающее фактическое сообщение об ошибке.Как создать виртуальную машину в представлении в рендере рендеринга Aurelia

enter image description here

В настоящее время я рендеринг все это в коде вручную в рендерер, но кажется, что было бы неплохо иметь HTML для все это определенно в HTML-файле вместе с ассоциированным js для обработки щелчка и наведения на значок. IOW, инкапсулируйте все элементы ошибки (значок с помощью всплывающего окна) в View/ViewModel, а затем в render() моего средства проверки правильности, как-то просто создайте новый экземпляр этого сразу после рассматриваемого элемента.

Это можно сделать? Я видел, как использовать элемент <compose></compose>, но я действительно стараюсь не добавлять это ко всем ящикам ввода моих форм.

Это то, что я в настоящее время в моем рендера:

import {ValidationError, RenderInstruction} from 'aurelia-validation' 

export class IconValidationRenderer { 
    render(instruction){ 
     //Unrender old errors 
     for(let {result, elements} of instruction.unrender){ 
      for(let element of elements){ 
       this.remove(element, result); 
      } 
     } 

     //Render new errors 
     for(let {result, elements} of instruction.render){ 
      for(let element of elements){ 
       this.add(element, result) 
      } 
     } 
    } 

    add(element, result){ 
     if(result.valid) 
      return 

     //See if error element already exists 
     if(element.className.indexOf("has-error") < 0){ 
      let errorIcon = document.createElement("i") 
      errorIcon.className = "fa fa-exclamation-circle" 
      errorIcon.style.color = "darkred" 
      errorIcon.style.paddingLeft = "5px" 
      errorIcon.id = `error-icon-${result.id}` 
      errorIcon.click = "" 
      element.parentNode.appendChild(errorIcon) 

      element.classList.add("has-error") 
      element.parentNode.style.alignItems = "center" 

      let errorpop = document.createElement("div") 
      let errorarrow = document.createElement("div") 
      let errorbody = document.createElement("div") 
      errorpop.id = `error-pop-${result.id}` 
      errorpop.className = "flex-row errorpop" 
      errorarrow.className = "poparrow" 
      errorbody.className = "flex-col popmessages" 
      errorbody.innerText = result.message 
      console.log("Computing position") 

      let elemRec = errorIcon.getBoundingClientRect() 
      let elemH = errorIcon.clientHeight 
      errorpop.style.top = elemRec.top - 10 + "px" 
      errorpop.style.left = elemRec.right + "px" 

      errorpop.appendChild(errorarrow) 
      errorpop.appendChild(errorbody) 
      element.parentNode.appendChild(errorpop) 
     } 
    } 

    remove(element, result){ 
     if(result.valid) 
      return 

     element.classList.remove("has-error") 
     let errorIcon = element.parentNode 
      .querySelector(`#error-icon-${result.id}`) 
     if(errorIcon) 
      element.parentNode.removeChild(errorIcon) 

     //Need to remove validation popup element 
    } 
} 

Спасибо за любую помощь вы можете предложить.

P.S. На данный момент я не внедряю клик или зависание, как я уже упоминал, - это то, что я хотел бы сделать, но я даже не уверен, как на данный момент. Было бы более прямолинейно, если я смогу составить виртуальную машину.

EDIT

Я указал на this статью кто-то на канале Aurelia GITTER. Я пробовал реализовать TemplatingEngine, но я не думаю, что это не так. Вот что у меня есть.

адд-человеко-dialog.js // VM, которая имеет форму с проверкой

import {TemplatingEngine,NewInstance} from 'aurelia-framework' 
import {ValidationController} from 'aurelia-validation' 
import {IconValidationRenderer} from './resources/validation/icon-validation-renderer' 

export class AddPersonDialog { 
    static inject = [NewInstance.of(ValidationController),TemplatingEngine] 

    constructor(vc, te){ 
     this.vc = vc 
     this.vc.addRenderer(new IconValidationRenderer(te)) 
    } 

значок-проверки-renderer.js

//Plus all the other bits that I posted in the code above 
constructor(te){ 
    this.te = te 
} 

add(element, result){ 
    if(result.valid) return 

    if(element.className.indexOf("has-error") < 0 { 
     //replaced there error icon code above with this (as well as a few different variations 
     let test = document.createElement("field-error-info") 
     element.parentNode.appendChild(test) 
     this.te.enhance({element: test}) 
    } 
} 

поле ошибок-инфо .html

<template> 
    <require from="./field-error-info.css" ></require> 

    <i class="fa fa-exclamation-circle" click.delegate="displayMessage = !displayMessage" mouseenter.delegate="displayMessage = true" mouseleave.delegate="displayMessage = false"></i> 
    <div show.bind="displayMessage" class="flex-row errorpop" style="left:300px"> 
     <div class="poparrow"></div> 
     <div class="flexcol popmessages">Message 1</div> 
    </div> 
</template> 

В конечном итоге <field-error-info></field-error-info> добавляется в DOM, но фактически не отображается. (Кстати, я также попытался добавить <require from='./elements/field-error-info'></require> в add-person-dialog.html.

ответ

2

Вы можете создать пользовательский элемент управления формой, который инкапсулирует значок ошибки и подсказку всплывающей подсказки.Элемент может выставить два контента слотов проекции, чтобы позволить прохождение в метке и ввода/выбора/и т.д.:

<template> 
    <div validation-errors.bind="errors" 
     class="form-group ${errors.length ? 'has-error' : ''}"> 

    <!-- label slot --> 
    <slot name="label"></slot> 

    <!-- input slot --> 
    <slot name="input"></slot> 

    <!-- icon/tooltip stuff --> 
    <span class="control-label glyphicon glyphicon-exclamation-sign tooltips" 
      show.bind="errors.length"> 
     <span> 
     <span repeat.for="errorInfo of errors">${errorInfo.error.message}</span> 
     </span> 
    </span> 
    </div> 
</template> 

Вот как он будет использоваться:

<template> 
    <require from="./form-control.html"></require> 

    <form novalidate autofill="off"> 

    <form-control> 
     <label slot="label" for="firstName" class="control-label">First Name:</label> 
     <input slot="input" type="text" class="form-control" 
      value.bind="firstName & validateOnChange"> 
    </form-control> 

    <form-control> 
     <label slot="label" for="lastName" class="control-label">Last Name:</label> 
     <input slot="input" type="text" class="form-control" 
      value.bind="lastName & validateOnChange"> 
    </form-control> 

    </form> 
</template> 

Живой пример: https://gist.run/?id=874b100da054559929d5761bdeeb651c

, пожалуйста, извините crappy tooltip css

+0

Awesome Jeremy! Спасибо тонны! – RHarris