hazaarlabs / hazaar-forms
Requires
- hazaarlabs/hazaar-mvc: >=2.5.14
- dev-master
- 2.0.1
- 2.0.0
- 1.9.3
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.1
- 1.7.0
- 1.6.1
- 1.6.0
- 1.5.6
- 1.5.5
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.2
- 1.4.1
- 1.4.0
- 1.3.1
- 1.3.0
- 1.2.11
- 1.2.10
- 1.2.9
- 1.2.8
- 1.2.7
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.12
- 1.1.11
- 1.1.10
- 1.1.9
- 1.1.8
- 1.1.7
- 1.1.6
- 1.1.5
- 1.1.4
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- 0.9.13
- 0.9.12
- 0.9.11
- 0.9.10
- 0.9.9
- 0.9.8
- 0.9.7
- 0.9.6
- 0.9.5
- 0.9.4
- 0.9.3
- 0.9.2
- 0.9.1
- 0.9.0
- dev-307-cache-queue-api-calls
- dev-273-function-to-convert-a-form-definition-into-an-json-schema-object
- dev-264-expandable-sections
- dev-234-file-inputs-do-not-work-as-list-fields
This package is auto-updated.
Last update: 2023-09-19 01:25:57 UTC
README
Hazaar 表单模块能够简化构建高级动态在线表单。
详细信息将很快提供。目前,这里是对使用表单的快速概述。
表单定义
表单定义正是如此。它们是定义您的表单字段及其操作方式的 JSON。这包括页面、部分、字段、验证等。
准备您的应用程序
现在正在使用一个新的应用程序子目录,称为 'forms'。因此,创建目录 {project_base}\application\forms 以存储您的表单定义。
创建一个简单的表单定义
这是一个开始使用的方法。文档将很快提供。
{
"name": "Testing and Development Form #1",
"pages": [
{
"sections": [
{
"label": "General Information",
"fields": [
{
"name": "name",
"required": true
},
"gender",
"dob",
"married"
]
}
]
},
{
"label": "Addresses",
"sections": [
{
"label": "Home",
"fields": [ "address1", "address2", "city", "country", "state" ]
}
]
}
],
"fields": {
"name": {
"type": "text",
"label": "Name",
"placeholder": "Type your full name here...",
"prefix": "Prefix",
"suffix": "Suffix"
},
"gender": {
"type": "select",
"label": "Gender",
"placeholder": "Please choose your gender...",
"options": {
"male": "Male",
"female": "Female"
}
},
"dob": {
"type": "date",
"label": "Date of Birth"
},
"country": {
"type": "select",
"label": "Country",
"options": {
"aus": "Australia",
"nz": "New Zealand"
}
},
"address1": {
"type": "text",
"label": "Address 1"
},
"address2": {
"type": "text",
"label": "Address 2"
},
"city": {
"type": "text",
"label": "City / Suburb"
},
"state": {
"type": "select",
"label": "State",
"options": {
"nsw": "New South Wales",
"act": "Australian Captial Territory"
}
},
"married": {
"type": "boolean",
"label": "Married"
}
}
}
目前只有 3 个必需元素。 name、pages 和 fields。
- name - 这是一个友好的标签,可以在表单布局中显示
- pages - 实际的页面定义。每个页面包含一个或多个部分。每个部分包含一个或多个字段。字段可以通过名称或对象声明来包含。
- fields - 定义您的表单中所有可用的字段。字段可以定义一次并在表单中多次使用。字段定义具有名称、类型、标签和一些类型相关的属性。
表单控制器
您的应用程序需要一个表单控制器来处理与表单前端的数据通信。用于此目的的 Hazaar\Controller\Forms 类基本上是一个您每天使用的 Hazaar\Controller\Action 类,但带有一些额外的有助于获取和传输数据的方法。
这里有一个我提前准备好的
<?php
class IndexController extends \Hazaar\Controller\Form {
private $cache;
/*
* Initialise all the bits we need. We call these in init so that they are
* only called in a single place. The cache object is used to store form
* data for this test. The form() method call is required to declare which
* form definition we are going to use.
*/
protected function init() {
$this->cache = new \Hazaar\Cache('file', array('use_pragma' => false));
$this->form('test1', array('id' => intval($this->request->get('id', 1))));
}
/*
* This is just like any other action defined in \Hazaar\Controller\Action
* Here we add the GUI view helper, which gives us a cool popup box to use,
* include out application.js script and set the view to use.
*/
public function index() {
$this->view->addHelper('gui');
$this->view->requires('application.js');
$this->view('index');
}
/*
* This is a simple example of a save method. Here all we do is take the
* form data and dump it into a cache object. A more advanced use would
* be to process the form data and store it in a database
*
* $params is the second argument from out forms() call in the init()
* method. This can be used to pass on a unique ID to identify the form
* data.
*/
public function save($model, $params = array()){
$this->cache->set('form-' . ake($params, 'id', 0), $model->get());
}
/*
* The load method is basically the reverse of the save method. In this
* example we from the form data out of the cache object. If it doesn't
* exist we are nice and return an empty array.
*/
public function load($params = array()){
if(!($out = $this->cache->get('form-' . ake($params, 'id', 0))))
$out = array();
return $out;
}
}
注意事项
init()和dex()定义在 Action 类中,因此工作方式与正常一样。save()和load()是简单的方法,是必需的。这些方法获取表单模块中的数据并将其传输出去,允许您的应用程序在它想要的地方存储和检索实际的表单数据。在这个例子中,我们只是将其缓存到一个文件中。$this->form('formname')的调用是必需的。这通常在 init 方法中完成,尽管这可能会改变,并且只是告诉表单模块我们正在使用哪个表单。这也给您的应用程序一个机会来定义一些额外的参数,这些参数将在每个 GET/POST 调用中来回传递。这通常用于记录 ID 或表单数据标识符。
现在我们只需要一个视图,一切就会工作,但我们将添加一些 JavaScript 来使一切正常。
表单视图
视图本身可以非常简单。然而,为了充分利用我们的表单,我们可以将 DOM 元素绑定到表单数据,并使其动态更新。
<div class="row">
<div class="col-xs-9">
<div class="panel panel-default">
<div class="panel-heading">
<div id="formPage" class="pull-right"></div>
<div id="formStatus">Initialising...</div>
</div>
<div class="panel-body" style="position: relative;">
<div class="well" id="frmTest">
<?=$this->layout();?>
</div>
</div>
<div class="panel-footer">
<button id="btnPrev" class="btn btn-default">Previous</button>
<button id="btnNext" class="btn btn-default pull-right">Continue</button>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="panel panel-default">
<div class="panel-heading">
<div id="formStatus">Summary</div>
</div>
<div class="panel-body">
<div class="form-group">
<label class="control-label">Name</label>
<div data-bind="name"></div>
</div>
<div class="form-group">
<label class="control-label">Gender</label>
<div data-bind="gender"></div>
</div>
<div class="form-group">
<label class="control-label">DOB</label>
<div data-bind="dob"></div>
</div>
</div>
</div>
<div id="saveButtons">
<button class="btn btn-default">Save</button>
<button class="btn btn-success" data-submit="true">Submit</button>
</div>
</div>
</div>
真正重要的是调用 $this->layout(),这实际上告诉表单控制器将表单放在哪里。
额外的 JavaScript
为了导航表单,我们需要添加一些额外的 JavaScript。决定内置导航虽然使事物更加自我包含,但不会允许非常好的视图集成。
$(document).ready(function () {
$('#frmTest').children('form').on('ready', function (e, def) {
$('#formStatus').html(def.name);
}).on('nav', function (e, page, pages) {
$('#formPage').html('Page ' + page + ' of ' + pages);
}).on('data', function (e, data) {
//Data is loaded so do stuff!
}).on('saved', function (e, data) {
var popupOps = { title: "Success", icon: "success", buttons: [{ label: 'OK', "class": "btn btn-default" }] };
if (data.submit === true)
$('<div>').html('Form data has been submitted successfully!').popup(popupOps);
else
$('<div>').html('Form data has been saved successfully!').popup(popupOps);
}).on('error', function (e, error) {
$('<div>').html([
$('<div>').html(error.str),
$('<div>').html([$('<strong>').html('Line: '), $('<span>').html(error.line)]),
$('<div>').html([$('<strong>').html('File: '), $('<span>').html(error.file)])
]).popup({ title: 'Form error', buttons: [{ label: 'OK', "class": "btn btn-default" }], icon: 'error' });
});
$('#btnPrev').click(function () {
$('#frmTest').children('form').form('prev');
});
$('#btnNext').click(function () {
$('#frmTest').children('form').form('next');
});
$('#saveButtons').children('button').click(function (e) {
var submit = ($(e.target).attr('data-submit') == 'true');
if ($(e.target).attr('data-submit') == 'true') {
$('<div>').html('Are you sure you want to submit this form?').popup({
title: "Confirm Submission",
icon: "question",
buttons: [
{
"label": "OK",
"class": "btn btn-success",
"action": function () {
$('#frmTest').children('form').form('save', false, { submit: true });
$(this).popup('close');
}
},
{
"label": "Cancel",
"class": "btn btn-default"
}
]
});
} else {
$('#frmTest').children('form').form('save', false);
}
});
});
这段代码将处理一些按钮的点击事件,这些按钮允许我们保存和提交表单。保存是默认方法,而提交会弹出一个确认框,并发送一些额外的数据来表示我们正在提交。我们可以在表单控制器的save()方法中随意处理这些数据。在这个例子中,我们的想法是可以边保存表单边提交,然后在最后导航页面离开或执行其他操作。
自定义输入
使用jQuery可以创建一个完全自定义的输入。添加自定义输入是一个高级功能,如果你选择走这条路,需要考虑一些事情。
- 你的代码负责渲染整个字段,包括标签。
- 你的代码负责处理事件,如onchange或onkeypress。
- 你的代码必须返回一个jQuery对象容器。
- 如果你想使输入能够正确与MVVM数据绑定器交互,你需要记得将
data-bind属性添加到实际的输入中(请参见下面的示例2)。
可用变量
你的函数中有两个全局变量可用。
- field包含字段定义,包括字段的当前值。这至少包含name和value属性。其余的是你在JSON字段定义中定义的内容。
- form是表单数据对象。你可以通过直接修改这个dataBinder对象来访问表单数据。
示例1 - 简单文本输入
下面是如何创建自定义输入的示例。这将生成一个没有样式和标签的文本输入,完全在JSON字段定义文件中定义。
{
"pages": [],
"fields": {
"custom": {
"type": "text",
"label": "A Simple Custom Input",
"render": "return $('<input type="text">').val(field.value);"
}
}
}
注意 - 请记住,上面的示例实际上不会做任何事情,因为我们没有处理任何更新表单数据的onChange事件。
示例2 - 较复杂的文本输入
这段代码创建了一个稍微复杂一点的文本输入,类似于内置的文本输入生成器。这个自定义输入定义在应用javascript的某个地方,作为一个函数调用,必须可访问并包含在表单控制器中(在控制器中,通常使用$this->require('yourscript.js');)。
function myCustomInput(field, form) {
var group = $('<div class="form-group">');
$('<label class="control-label">').attr('for', field.name).html(field.label).appendTo(group);
$('<input type="text" placeholder="custom input" class="form-control">')
.attr('data-bind', field.name)
.val(field.value)
.appendTo(group)
.change(function () {
form.data[field.name] = $(this).val();
});
return group;
};
然后我们可以使用与示例1类似的JSON字段定义,只是我们调用我们的函数并传递field和form变量。
{
"pages": [],
"fields": {
"custom": {
"type": "text",
"label": "A Simple Custom Input",
"render": "return myCustomInput(field, form);"
}
}
}
结论
就这些。这个模块非常新,仍在开发中,所以如果事情变化很大,请不要感到惊讶。