Files
yii2/docs/guide-zh-CN/input-forms.md
2017-08-07 13:11:24 +03:00

214 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

创建表单
====
基于活动记录(ActiveRecord)的表单ActiveForm
-----------------------
在yii中使用表单的主要方式是通过[[yii\widgets\ActiveForm]]。当某个表单是基于一个模型时,应该首选这种方式。此外,在[[yii\helpers\Html]]中有很多实用的方法为表单添加按钮和帮助文档。
在客户端显示的表单,大多数情况下都有一个相应的[模型](structure-models.md),用来在服务器上验证其输入的数据(可在[输入验证](input-validation.md)一节获取关于验证的细节)。当创建一个基于模型的表单时,第一步是定义模型本身。该模型可以是一个基于[活动记录](db-active-record.md)的类,表示数据库中的数据,也可以是一个基于通用模型的类(继承自[[yii\base\Model]]),来获取任意的输入数据,如登录表单。
> Tip: 如果一个表单的输入域与数据库的字段不匹配,或者它存在只适用于它的特殊的格式或者方法,则最好为它创建一个单独的继承自[[yii\base\Model]]的模型。
在接下来的例子中,我们展示了通用模型如何用于登录表单:
```php
<?php
class LoginForm extends \yii\base\Model
{
public $username;
public $password;
public function rules()
{
return [
// 在这里定义验证规则
];
}
}
```
在控制器中,我们将传递一个模型是实例到视图,其中[[yii\widgets\ActiveForm|ActiveForm]]小部件将用来显示表单。
```php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$form = ActiveForm::begin([
'id' => 'login-form',
'options' => ['class' => 'form-horizontal'],
]) ?>
<?= $form->field($model, 'username') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<div class="form-group">
<div class="col-lg-offset-1 col-lg-11">
<?= Html::submitButton('Login', ['class' => 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end() ?>
```
### 用 `begin()` 和 `end()` 包裹 <span id="wrapping-with-begin-and-end"></span>
在上面的代码中,[[yii\widgets\ActiveForm::begin()|ActiveForm::begin()]] 不仅创建了一个表单实例,同时也标志的表单的开始。所有在[[yii\widgets\ActiveForm::begin()|ActiveForm::begin()]]与[[yii\widgets\ActiveForm::end()|ActiveForm::end()]]之中的内容都会被HTML中的 `<form>`标签包裹。与其他小部件一样,你可以制定一些选项,通过传递数组到到 `begin` 中来配置小部件。在这种情况下一个额外的CSS类和ID会在 `<form>` 标签中使用。要查看更多可用的选项请查看API文档的 [[yii\widgets\ActiveForm]]。
### ActiveField <span id="activefield"></span>
为了在表单中创建表单元素与元素的标签以及任意适用的Javascript验证需要使用[[yii\widgets\ActiveForm::field()]|ActiveForm::field()]方法,其返回一个[[yii\widgets\ActiveField]]实例。当直接输出该方法时,结果是一个普通的(文本)输入。要自定义输出,可以附加上[[yii\widgets\ActiveField|ActiveField]]的其他方法来一起调用:
```php
// 密码输入框
<?= $form->field($model, 'password')->passwordInput() ?>
// 增加提示与自定义标签
<?= $form->field($model, 'username')->textInput()->hint('Please enter your name')->label('Name') ?>
// 创建一个HTML5邮件输入元素
<?= $form->field($model, 'email')->input('email') ?>
```
它会通过[[yii\widgets\ActiveField|ActiveField]]中定义的表单字段来创建`<label>`,`<input>`以及其他标签。input输入框的name属性会自动的根据[[yii\base\Model::formName()| form name]] 以及属性来来创建。例如,对于上面例子中的`username`输入字段的name属性将是`LoginForm[username]`。这种命名方式会使登录表单的所有属性在服务器端的`$_POST['LoginForm']`数组中是可用。
> Tip如果你在一个表单中只有一个模型并且想要简化input输入名称你可以覆盖模型的[[yii\base\Model::formName()|formName()]]方法,使其返回一个空的字符串,以此来跳过数组部分。这在[GridView](output-data-widgets.md#grid-view)的过滤模型创建更好的URLs时是非常有用的。
指定模型是属性时可以以更复杂的方式来完成。比如,当上传多个文件时,或者选择多个多个项目时,可能会需要一个数组值,你可以通过附加`[]`来指定它的属性名称:
```php
// allow multiple files to be uploaded:
echo $form->field($model, 'uploadFile[]')->fileInput(['multiple'=>'multiple']);
// allow multiple items to be checked:
echo $form->field($model, 'items[]')->checkboxList(['a' => 'Item A', 'b' => 'Item B', 'c' => 'Item C']);
```
命名表单元素,如提交按钮时需要小心。在[JQuery](https://api.jquery.com/submit/)中有一些保留名词,可能会导致冲突:
> 表单和它们的子元素不应该使用与表单的属性冲突的input name或id例如submitlength或者 method。 要检查你的标签是否存在这些问题,一个完整的规则列表详见 DOMLint。
将额外的HTML标签添加到表单中可以通过使用纯HTML或者使用[[yii\helpers\Html|Html]]的方法,比如上述例子中的帮助类的做法[[yii\helpers\Html::submitButton()|Html::submitButton()]]。
> Tip如果你的应用程序正在使用Twitter的Bootstrap CSS样式你可以选择使用[[yii\bootstrap\ActiveForm]]代替[[yii\widgets\ActiveForm]]这个表单继承自后者并且使用Bootstrap特有的样式初始化表单的输入框。
> Tip: 为了使用星号对必填字段进行样式,你可以使用下面的CSS样式
>
> ```css
> div.required label.control-label:after {
> content: " *";
> color: red;
> }
> ```
创建列表 <span id="creating-activeform-lists"></span>
-----------------------
这里有3中类型的列表
- 下拉列表
- 单选列表
- 多选列表
为了创建列表,你必须先为它准备选项。这些选项可以手动准备如下:
```php
$items = [
1 => 'item 1',
2 => 'item 2'
]
```
或者直接从数据库中检索:
```php
$items = Category::find()
->select(['label'])
->indexBy('id')
->column();
```
这些 `$items` 必须能被不同的列表组件处理。列表输入框的值(以及当前选中的选项)将会根据当前`$model`的属性的值而自动的生成。
#### 创建一个下拉选择列表 <span id="creating-activeform-dropdownlist"></span>
我们可以使用活动领域的[[yii\widgets\ActiveField::dropDownList()]] 方法来创建一个下拉列表:
```php
/* @var $form yii\widgets\ActiveForm */
echo $form->field($model, 'category')->dropdownList([
1 => 'item 1',
2 => 'item 2'
],
['prompt'=>'Select Category']
);
```
#### 创建一个单选列表 <span id="creating-activeform-radioList"></span>
我们可以使用活动领域的[[yii\widgets\ActiveField::radioList()]] 方法来创建一个下拉列表:
```php
/* @var $form yii\widgets\ActiveForm */
echo $form->field($model, 'category')->radioList([
1 => 'radio 1',
2 => 'radio 2'
]);
```
#### 创建一个多选列表: <span id="creating-activeform-checkboxList"></span>
我们可以使用活动领域的[[yii\widgets\ActiveField::checkboxList()]] 方法来创建一个下拉列表:
```php
/* @var $form yii\widgets\ActiveForm */
echo $form->field($model, 'category')->checkboxList([
1 => 'checkbox 1',
2 => 'checkbox 2'
]);
```
使用Pjax <span id="working-with-pjax"></span>
-----------------------
[[yii\widgets\Pjax|Pjax]]组件允许你更新一个页面的某些部分而不用从新加载整个页面。你可以在提交表单后使用Pjax来更新表单或者替换表单的某些内容。
你可以配置[[yii\widgets\Pjax::$formSelector|$formSelector]]来指定那些表单的提交会触发pjax。如果你没有设置所有包含`data-pjax`属性并且含有封闭的Pjax内容的表单将会触发pjax请求。
```php
use yii\widgets\Pjax;
use yii\widgets\ActiveForm;
Pjax::begin([
// Pjax options
]);
$form = ActiveForm::begin([
'options' => ['data' => ['pjax' => true]],
// more ActiveForm options
]);
// ActiveForm content
ActiveForm::end();
Pjax::end();
```
> Tip: 注意小心[[yii\widgets\Pjax|Pjax]]内部的链接,因为响应仍可能在组件内部呈现。为了避免这种现象,可以使用`data-pjax="0"`这个HTML属性。
#### 提交按钮和文件上传
由于`JQuery.serializeArray()`在处理[文件内容](https://github.com/jquery/jquery/issues/2321)和[提交按钮的值](https://github.com/jquery/jquery/issues/2321)时存在已知的问题,同时也为了推广`FormData`在HTML5中的使用它将直接被弃用而不是等待修复。
这意味着官方对`FormData`在文件上传ajax提交按钮的值以及组件[[yii\widgets\Pjax]]的使用上取决于[浏览器](https://developer.mozilla.org/en-US/docs/Web/API/FormData#Browser_compatibility)的支持。
扩展阅读 <span id="further-reading"></span>
---------------
下一节 [输入验证](input-validation.md) 处理提交的表单数据的服务器端验证, 以及 ajax- 和客户端验证。
要学会有关表格的更复杂的用法,你可以查看以下几节:
- [收集列表输入](input-tabular-input.md) 同一种类型的多个模型的采集数据。
- [多模型同时输入](input-multiple-models.md) 在同一窗口中处理多个不同的模型。
- [文件上传](input-file-upload.md) 如何使用表格来上传文件。