angular-schema-form 自動表單生成


基本用法

通過bower安裝之后,將schemaForm模塊載入到模塊定義中,fuse中安裝第三方包需要在app/core/core.module.js中聲明。

然后在controller里面,將schema、form、model屬性賦給$scope,schema定義了數據結構,form定義了UI,model綁定了用戶的輸入。

angular.module('myModule', ['schemaForm'])
       .controller('FormController', function($scope) {
  $scope.schema = {
    type: "object",
    properties: {
      name: {
        type: "string",
        minLength: 2,
        title: "Name",
        description: "Name or alias" 
      },
      title: {
        type: "string",
        enum: ['dr','jr','sir','mrs','mr','NaN','dj']
      }
    },
    "required": ["name"]   // 定義強制字段
  };   // 表單字段定義

  $scope.form = [
    {
      key: "name",
      validationMessage: {
        200: 'Seriously? Value {{value}} totally shorter than {{schema.minLength}}, which is NOT OK.',
        302: "This field is like, uh, required?"
      }
    },
    "title",
    {
      type: "submit",
      title: "Save"
    }
  ];   // 定義表單各個域以及他們的行為(錯誤信息、提交按鈕等)

  $scope.model = {};  // 用戶的輸入綁定到這里
});

然后在模板中,通過ng-controller載入,使用sf-schema、sf-form、sf-model指令。

<div ng-controller="FormController">
    <form sf-schema="schema" sf-form="form" sf-model="model"></form>
</div>

sf-schema指令不一定要在form標簽中,實際上可以放在一個div中,比如需要有一個自己編寫的按鈕或表單域。

 

處理提交

Schema Form並不在意你怎么處理你的數據,處理提交最推薦的方式是使用ng-submit指令,同時建議用name屬性從而可以在FormController中訪問到它,並且驗證合法性。

你可以通過broadcast一個事件(schemaFormValidate)來強制執行校驗。

$scope.onSubmit = function(form) {
  // First we broadcast an event so all fields validate themselves
  $scope.$broadcast('schemaFormValidate');

  // Then we check if the form is valid
  if (form.$valid) {
    // ... do whatever you need to do with your data.
  }
}

關於$scope.$broadcast的用法參考stackoverflow

 

表單更新

Schema Form監聽sf-form和sf-schema,當他們改變的時候會重畫整個表單,但也不是完全改變(……不知道文檔這里在講什么)

如果想要手動更新表單,可以調用schemaFormRedraw事件。

function Ctrl($scope) {
  $scope.removeLastField = function() {
    $scope.form.pop()
    $scope.$broadcast('schemaFormRedraw')
  }
}

 

全局屬性

Schema Form通過sf-options來設定全局屬性,sf-options應該和sf-schema放在一起。它接收一個對象,有以下屬性和取值。

屬性 類型 描述
supressPropertyTitles boolean 默認下沒有設置schema的title時,會用它的名字作為title,將本屬性設為true會取消這個默認行為
formDefaults object 一個對象,定義到所有的表單項中
validationMessage object or function  
setSchemaDefaults boolean  
destroyStrategy string  
pristine Object {errors, success}  
validateOnRender boolean  

formDefaults屬性最常用的是設置ngModelOptions,以下設置會使表單的每項都帶上一個屬性:ng-model-options="form.ngModelOptions"

<div ng-controller="FormController">
    <form sf-schema="schema"
          sf-form="form"
          sf-model="model"
          sf-options="{ formDefaults: { ngModelOptions: { updateOn: 'blur' } }}"></form>
</div>

關於ng-model-options:常用於將“model與用戶輸入實時同步”改為“model在用戶輸入完(blur之后)再同步”。參看文檔

 

校驗信息

Schema Form使用tv4來校驗表單。以下幾個方法可以改變默認的校驗信息:

  1. 改變sfErrorMessages的默認值(通過其provider),這會將校驗信息設置到sf-schema的所有實例中。
  2. 用全局屬性validationMessage
  3. 用表單域屬性validationMessage

如果一個定義好的驗證錯誤代碼在表單域屬性中找不到,schema form會找全局屬性,如果沒有則用它的默認值(不知道文檔在說什么……)

錯誤的類型是通過匹配tv4的錯誤碼

信息插入

通過value、shcema等變量可以讀取到用戶輸入的值,以及schema中定義的值,從而使得錯誤信息動態變化。(error:錯誤類型碼,這個應該也常用,比如說定義好一個錯誤信息的數組errorMessage[],通過errorMessage[error]就能讀取對應的錯誤信息。)

$scope.form = [
  {
    key: "name",
    validationMessage: {
      200: 'Seriously? Value {{value}} totally shorter than {{schema.minLength}}, which is NOT OK.',
      302: "This field is like, uh, required?"
    }
  },
  "title",
  {
    type: "submit",
    title: "Save"
  }
];

*這里的{{value}}並不能正常顯示用戶的輸入,待解決。

 

自定義校驗

有一些需要后端協助的校驗。Schema Form允許我們注入任意的校驗信息到任意的表單域中。

這是通過schemaForm.error事件開始,然后在表單域的key結束。它需要兩個參數,第一個是錯誤碼/錯誤名,第二個是校驗信息/布爾值。使用的是$scope.$broadcast。

例子:在后台校驗發現用戶名重復時,調用以下語句可以讓表單不合法,並顯示信息:

$scope.$broadcast('schemaForm.error.name','usernameAlreadyTaken','The username is already taken');

如果后台校驗發現用戶名可以使用,調用以下語句可以讓表單合法,這時第二個參數要為true:

$scope.$broadcast('schemaForm.error.name','usernameAlreadyTaken',true);

使用ngModelController

另一個校驗表單的方法是使用ngModelController,Schema Form可以將ngModelController暴露在一個表單域中,給一個定義了表單的函數(……又不知道在說什么)。或者你可以用一個shorthand,就是通過加$validators和$asyncValidators。

我的簡單理解:就是$validators和$asyncValidators都是用函數來進行校驗,區別是一個是同步的一個是異步的,下面是$asyncValidators的例子:

$scope.form = [
  {
    key: 'name',
    placeholder: 'Anything but "Bob"',
    $asyncValidators: {
      'async': function(name) {
        var deferred = $q.defer();
        $timeout(function(){
          if (angular.isString(name) && name.toLowerCase().indexOf('bob') !== -1) {
            deferred.reject();
          } else {
            deferred.resolve();
          }
        }, 1500);
        return deferred.promise;
      }
    },
    validationMessage: {
      'async': "Wooohoo thats not an OK name!"
    }
  },
  ....
];

上面的代碼會在輸入name表單域時,經過1.5秒后校驗用戶的輸入是不是bob(忽略大小寫)

 

表單的默認schema

比較推薦的做法是將表單元素的UI和驗證分開,但是如果確實需要在schema中定義表單元素的UI,則可以通過x-schema-form屬性來進行設置。x-schema-form需要是一個對象。

{
  "type": "object",
  "properties": {
    "comment": {
      "type": "string",
      "title": "Comment",
      "x-schema-form": {
        "type": "textarea",
        "placeholder": "Don't hold back"
      }
    }
  }
}

默認表單type

在schema定義表單的type,對應生成的表單的類型如下表。

 

Form定義

form的定義有三種形式:

  1. 星號"*",代表整個schema都使用默認形式
  2. 一個字符串,標識屬性名:"name"
  3. 一個對象,定義了表單的各種屬性(placeholder、校驗信息等等):{ key: "name" , ... }

另外在$scope.form中可以重寫表單域的順序和它的type。

$scope.schema = {
  "type": "object",
  "properties": {
    "surname":     { "type": "string" },
    "firstname":   { "type": "string" },
  }
};

$scope.form = [
  "firstname",
  {
    key: "surname",
    type: "select",
    titleMap: [
      { value: "Andersson", name: "Andersson" },
      { value: "Johansson", name: "Johansson" },
      { value: "other", name: "Something else..."}
    ]
  }
];

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM