当前位置: 首页 > 软件库 > 程序开发 > >

ember-do-forms

授权协议 MIT License
开发语言 JavaScript
所属分类 程序开发
软件类型 开源软件
地区 不详
投 递 者 顾永福
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

ember-do-forms

An Ember forms library that handles the icky parts of forms that you don't want to do, but makes no other assumptions otherwise.

Get started with:

ember install ember-do-forms

Philosophy

My experience with my ambitious application has proven that other (maintained) form builder addons either do too much, or are hard to customize. So I created ember-do-forms because it assumes very little about my form needs.

The basic idea for ember-do-forms is simple: assume as little as possible about my HTML and CSS structure, while providing some syntactic sugar for the icky parts.

For example, should forms validate my inputs? I'd argue that forms are just UX glue for your data, so forms shouldn't do that. Still I'd like validation UX (CSS, text, etc) to be handled by the form builder because it's a big chunk of boilerplate.

Another icky part is customisation, which most other form builder addons fail short on in varying degrees.

Features

Table of contents

  1. Usage
  2. Configuration
  3. Contributing
  4. Credits

Usage

Basic usage

{{#do-form object submit=(action 'saveTask') as |form|}}

  {{#form.do-field propertyName as |field|}}
    {{field.do-label labelText}}
    {{field.do-control controlType}}
    {{field.do-feedback}}
    {{field.do-hint hintText}}
  {{/form.do-field}}

  {{form.input-field propertyName controlType='email' label='Label' hint='Hint'}}

  <button type='submit'>Save</button>
{{/do-form}}
  • do-form is just a component that wraps components
  • object is the object the form binds to. It's the only positional param.
  • propertyName is the property the field binds to on the object.
  • labelText is the text to display for the label
  • controlType is the type of control to render. Valid values are textarea, select, or a valid value for the HTML input type attribute. For example {{field.do-control controlType='checkbox'}} will render a <input type="checkbox" and {{field.do-control controlType='select'}} will render a <select>.
  • submit pass in any action you want there. Or not, because it isn't required. Works great with ember-concurrency!
  • {{do-feedback}} shows the validation error message if it exists. It is bound by default to field.errorMessage.
  • {{do-hint}} shows any hint text you want via the hintText parameter.
  • use any type of button you want. Use a bare <button type='Submit'>, use it with ember-async-button or do it with style.

Input field

You can also use the {{ember-do-forms/input-field}} component to combine all of the goodness of the {{do-field}} component (and its contextual components) into a single line:

{{#do-form object submit=(action 'saveTask') as |form|}}
  {{form.input-field 'lastName' label='Last Name' hint='First name followed by last name'}}

  <button type='submit'>Save</button>
{{/do-form}}

If you want to skip labels and hints, just omit the label and hint arguments.

Also the classNames of its rendered sub-components can be modified using labelClasses, controlClasses, feedbackClasses and hintClasses.

Checkbox field

Same idea as the {{ember-do-forms/input-field}} component but providing some syntactic sugar for checkboxes.

{{#do-form object as |form|}}
  {{form.checkbox-field 'profileVisible' label='Profile visible' hint='Make your profile visible for the rest of the world?'}}
{{/do-form}}

If you want to skip the hint, just omit the hint argument. The same classNames that can be applied to the input-field also apply to the checkbox-field.

CSS customizations

You can customize the rendered CSS by modifying the default config. But you can also customize classes by individual component.

{{#do-form user classNames='my-custom-form-class' as |form|}}

  {{#form.do-field 'fullName' classNames='my-custom-field-class' as |field|}}
    {{field.do-label 'fullName' classNames='my-custom-label-class'}}
    {{field.do-control classNames='my-custom-control-class'}}
    {{field.do-feedback classNames='my-custom-feedback-class'}}
    {{field.do-hint 'First name, followed by last name' classNames='my-custom-hint-class'}}
  {{/form.do-field}}

{{/do-form}}

Component block form

You can modify the contents of a field easily. Below there is a Bootstrap 4 custom checkbox for example. The default tagName for a field is <div>.

{{#do-form user as |form|}}

  {{#form.do-field 'profileVisible' classNames='form-group' as |field|}}
    {{#field.do-label classNames='custom-control custom-checkbox'}}
      {{field.do-control 'checkbox' classNames='custom-control-input'}}
      <span class="custom-control-indicator"></span>
      <span class="custom-control-description">Profile visible?</span>
    {{/field.do-label}}
    {{field.do-hint 'Check this to make your profile visible' classNames='form-text text-muted'}}
  {{/form.do-field}}

{{/do-form}}

You can also modify the content of the {{do-control}} component. Use whatever you like, the context has access to id, value and validationClass, so your custom control will just work™. The default tagName is ''.

{{#do-form user as |form|}}

  {{#form.do-field 'customValue' as |field|}}
    {{field.do-label 'Custom Field'}}
    {{#field.do-control as |context|}}
      <input value={{context.value}} id={{context.id}} class="{{context.validationClass}}">
    {{/field.do-control}}
    {{field.do-feedback}}
  {{/form.do-field}}

{{/do-form}}

The {{do-feedback}} component can be easily customized as well. Just pass a block and it will have access to the error message, and displays only if there is one. The caveat here is that the component tag name should only be configured via wrapperTagName, and the reason is that this component should be hidden unless an error message is present. The default wrapperTagName is <div>.

{{#do-form user as |form|}}

  {{#form.do-field 'firstName' as |field|}}
    {{field.do-label 'First Name'}}
    {{field.do-control 'text'}}
    {{#field.do-feedback wrapperTagName='span' as |message|}}
      {{tooltip-on-component text=message}}
    {{/field.do-feedback}}
  {{/form.do-field}}

{{/do-form}}

The {{do-hint}} component is very easy to customize. Just pass a block and it will have access to hintText. The default tagName is <small>.

{{#do-form user as |form|}}

  {{#form.do-field 'fullName' as |field|}}
    {{field.do-label 'fullName'}}
    {{field.do-control 'text'}}
    {{field.do-feedback}}
    {{#field.do-hint 'First name, followed by last name' as |hintText|}}
      {{tooltip-on-component text=hintText}}
    {{/field.do-hint}}
  {{/form.do-field}}

{{/do-form}}

Test selectors

If you have added the excellent ember-test-selectors addon to your project you can freely use data-test-* to components that have tags and the ember-test-selectors will work as advertised. It doesn't work though for components that are wrapper components for other components, which ember-do-forms uses in many places (and other form builders use them as well).

You can learn more about why you should use ember-test-selectors by watching this video.

You can turn on the auto generation of data-test-* attributes by changing the default configuration:

module.exports = function(environment) {
  var ENV = {
    'ember-do-forms': {
      autoDataTestSelectors: true
    }
  };
};

Now, given you have something like:

{{#do-form user as |form|}}
  {{form.input-field 'lastName' label='Last name' hint='What your teacher calls you'}}
{{/do-form}}

You can use testSelector in your acceptance tests:

  • find(testSelector('do-field', 'lastName'));
  • find(testSelector('do-label', 'lastName'));
  • find(testSelector('do-control', 'lastName'));
  • find(testSelector('do-feedback', 'lastName'));
  • find(testSelector('do-hint', 'lastName'));

You can also manually set the attributes:

{{field.do-control 'lastName' data-test-do-control='mySpecialSelector' }}

The caveat is that the names of the data-test-* attributes must match the component names for do-control, do-feedback and input-field components (which are tagless), and only those attributes are supported. For components with tags, like do-form, do-field, do-label and do-hint, these restrictions don't apply.

Component customizations

If you have more complex components for controls for example, rest assured, you can use them. Even some context gets passed in to your custom components!

{{#do-form user as |form|}}
  {{#form.do-field 'customValue'
    labelComponent='my-very-smart-i18n-label'
    controlComponent='my-fancy-datepicker'
    feedbackComponent='my-fancy-error-message'
    hintComponent='my-hint' as |field|}}

    <!-- This is will now render 'my-very-smart-i18n-label' -->
    {{field.do-label}}

    <!-- This is will now render 'my-fancy-datepicker' -->
    {{field.do-control}}

    <!-- This is will now render 'my-fancy-error-message' -->
    {{field.do-feedback}}

    <!-- This is will now render 'my-hint' -->
    {{field.do-hint}}
  {{/form.do-field}}
{{/do-form}}

Configuration

The default configuration for ember-do-forms is very light.

module.exports = function(environment) {
  var ENV = {
    'ember-do-forms': {
      // The path to be read on the object for an errors array
      errorsPath: 'validations.attrs.{PROPERTY_NAME}.errors',

      // Auto generate relevant data-test-* for components
      // Overridable per component
      autoDataTestSelectors: false,

      // CSS classes to be applied to components
      // Overridable per component
      defaultClasses: {
        form: [],
        field: [],
        label: [],
        control: [],
        feedback: [],
        hint: []
      },

      // CSS classes to be applied to do-field and do-control
      // components based on the validation state of the object
      validationClasses: {
        fieldSuccess: [],
        fieldError: [],
        controlSuccess: [],
        controlError: []
      }
    }
  };
};

You can easily extend this configuration. For example Bootstrap 4 classes:

module.exports = function(environment) {
  var ENV = {
    'ember-do-forms': {
      defaultClasses: {
        form: [],
        field: ['form-group'],
        label: ['col-form-label'],
        control: ['form-control'],
        feedback: ['form-control-feedback'],
        hint: ['form-text', 'text-muted'],
      },
      validationClasses: {
        fieldSuccess: ['has-success'],
        fieldError: ['has-danger'],
        controlSuccess: ['form-control-success'],
        controlError: ['form-control-danger']
      }
    }
  };
};

Contributing

Any contribution, be it an issue, a feature or a bugfix is greatly appreciated ❤️

Also, if your feature or bugfix adheres to ember-do-forms's philosophy and is tested, I will give you commit rights.

Credits / Inspiration

I'm extremely thankful for the contributors of these projects as they've been a huge inspiration for me. From being an absolute beginner and not knowing what contextual components are, I have learned a lot by looking at the code and just experimenting and asking questions.

 相关资料
  • do

    描述 (Description) 提供块时,此函数执行,就像BLOCK是一个函数一样,返回块中计算的最后一个语句的值。 当提供EXPR时,请执行EXPR指定的文件,就像它是另一个Perl脚本一样。 如果提供子程序SUB,则使用LIST作为参数执行子程序,如果已定义SUB,则引发异常。 语法 (Syntax) 以下是此函数的简单语法 - do BLOCK do EXPR do SUB(LIST)

  • do

    do 当 Observable 产生某些事件时,执行某个操作 当 Observable 的某些事件产生时,你可以使用 do 操作符来注册一些回调操作。这些回调会被单独调用,它们会和 Observable 原本的回调分离。

  • do

    do构造还用于使用LISP执行迭代。 它提供了一种结构化的迭代形式。 do语句的语法 - (do ((variable<sub>1</sub> value<sub>1</sub> updated-value<sub>1</sub>) (variable<sub>2</sub> value<sub>2</sub> updated-value<sub>2</sub>)

  • do

    do / tap 函数签名: do(nextOrObserver: function, error: function, complete: function): Observable Transparently perform actions or side-effects, such as logging. 透明地执行操作或副作用,比如打印日志。 If you are using as a p

  • 一个无后端待办事项应用,数据用 LeanCloud 进行同步。 简介 这是一个无后端的待办事项应用,数据用 LeanCloud 进行同步,也是我的第三个 iOS 项目。 做这个项目的初衷是想比较全面地体现我的前后端水平,该同步算法从整理思路到实现 95% 的代码(意为接近稳定)花了两周时间,除思路外没有任何代码可以参考(反正我是没有找到... 界面设计来源于 DO ,部分素材和界面为本人设计。 该

  • GNOME Do 与 Katapult 和 GNOME Launch Box 很相似,它能根据用户键入的内容进行自动匹配,从而快速打开系统中已有的程序、文件、书签等。不仅如此,GNOME Do 还包括插件,从而能够做更多事。 GNOME Do 可用于 GNOME、KDE、Xfce 等桌面环境