flsouto/htwidget

此包的最新版本(1.0.2)没有可用的许可信息。

定义表单小部件类型的抽象类

1.0.2 2017-03-31 02:12 UTC

This package is not auto-updated.

Last update: 2024-09-23 15:15:35 UTC


README

概述

这个类可以被用来定义不同类型的小部件。但什么是小部件?小部件是一个具有某种状态并允许用户与服务器或后端进行通信的交互式字段/元素。请注意,并非所有表单字段都是交互式的。例如,一个隐藏字段(hidden field)尽管具有状态,但并不提供任何形式的直接交互。在我看来,一个按钮也不是小部件,因为它不允许除了点击之外的其他复杂交互。另一方面,一个输入文本字段或复选框可以被认为是小部件,因为它们确实具有状态并需要某种形式的交互。在本文档中,我们将看到如何实现一个简单的继承自 HtWidget 的 TextField 类。

注意:很多功能都是从更基本的抽象类 HtField 继承而来的。如果您在理解这里被重用的某些功能时遇到困难,请参阅此文档

安装

运行 composer

composer require flsouto/htwidget

使用方法

以下我们将实现一个简单的 TextField 类。请注意它,因为我们将在整个文档中使用它来了解从 HtWidget 继承的所有功能。

<?php

class TextField extends HtWidget{

	function __construct($name){
		parent::__construct($name);
		// By default all HtWidget instances have a default, random id.
		// We want to change that so the id is always the name of the field itself.
		$this->attrs['id'] = $name;
	}

	// All concrete HtWidget implementations must define a renderWritable method
	function renderWritable(){
		$attrs = $this->attrs;
		$attrs['value'] = $this->value();
		echo '<input '.$attrs.' />';
	}

	// All concrete HtWidget implementations must define a renderReadonly method
	function renderReadonly(){
		$attrs = $this->attrs;
		echo "<span ".$attrs.">".$this->value()."</span>";
	}

}

在下一个示例中,我们将实例化新定义的类并渲染它。

<?php
require_once('vendor/autoload.php');

$field = new TextField('email');
$field->context(['email'=>'someuser@domain.com']);

echo $field;

请注意,默认情况下,小部件以“可写模式”渲染。

<div class="widget email" style="display:block">
 <input id="email" name="email" value="someuser@domain.com" />
 <div style="color:yellow;background:red" class="error">
 </div>
</div>

切换到只读模式

要渲染小部件的只读版本,只需调用具有正参数的 readonly 设置器即可。

require_once('vendor/autoload.php');

$field = new TextField('email');
$field->context(['email'=>'someuser@domain.com'])
	->readonly(true);

echo $field;

输出

<div class="widget email" style="display:block">
  <span>someuser@domain.com</span>
 <div style="color:yellow;background:red" class="error">
 </div>
</div>

了解其工作原理

围绕主要元素的所有额外标签都是默认生成的。当我们调用 echo $field 时,会调用 HtWidget::render() 方法,它生成一个包含 HtWidget::renderInner() 输出的包装器,然后它再决定我们处于哪种模式,并调用相应的 renderReadonlyrenderWritable 方法,以及错误消息。因此,如果您只想显示内部内容而不显示包装器,您必须调用 renderInner() 方法。

$field->renderInner()

以行内方式显示小部件

默认情况下,小部件以块模式渲染,这意味着它占满整行。如果您希望它出现在之前打印的内容所在的同一行中,请使用 inline 设置器。

$field = new TextField('username');
$field->inline(true);

echo $field;

输出

<div class="widget username" style="display:inline-block;vertical-align:text-top">
 <input id="username" name="username" value="" />
 <div style="color:yellow;background:red" class="error">
 </div>
</div>

标签

默认情况下,小部件渲染时不带相关标签。如果您希望它显示出来,则必须指定一个。

$field = new TextField('product_name');
$field->label('Product Name');

echo $field;

输出

<div class="widget product_name" style="display:block">
 <label style="display:block" for="product_name">Product Name</label>
 <input id="product_name" name="product_name" value="" />
 <div style="color:yellow;background:red" class="error">
 </div>
</div>

您可以通过传递关联数组来更改标签的属性。在这种情况下,您必须使用特殊的 text 属性来设置标签的文本。

$field = new TextField('product_name');
$field->label(['text'=>'Product Name', 'class'=>'some_class']);

echo $field;

输出

<div class="widget product_name" style="display:block">
 <label style="display:block" class="some_class" for="product_name">Product Name</label>
 <input name="product_name" value="" />
 <div style="color:yellow;background:red" class="error">
 </div>
</div>

默认情况下,标签在控件上方渲染。如果您希望它在同一行显示,则可以使用特殊的 inline 属性。

$field = new TextField('name');
$field->label(['text'=>'Name','inline'=>true]);

echo $field;

输出

<div class="widget name" style="display:block">
 <label style="display:inline-block;margin-right:10px" for="name">Name</label>
 <input id="name" name="name" value="" />
 <div style="color:yellow;background:red" class="error">
 </div>
</div>

设置字段为必填

调用 required 方法,传递字段为空时显示的错误信息。

$field = new TextField('name');
$field
	->required('Name is required!')
	->context(['name'=>'']);

echo $field->validate();

输出

Name is required!

激活错误消息

默认情况下,如果内部发生任何验证错误,错误信息不会在字段旁边显示。您可以通过调用带有正值的 error 方法来更改此设置。

$field = new TextField('name');
$field
	->required('Name is required!')
	->context(['name'=>''])
	->error(true);

echo $field;

输出

<div class="widget name" style="display:block">
 <input name="name" value="" />
 <div style="color:yellow;background:red" class="error">
    Name is required!
 </div>
</div>

您可以通过向错误函数传递一个属性数组来自定义错误信息标签。

$field = new TextField('name');
$field->required('Name is required!')
	->context(['name'=>''])
	->error(['display'=>true,'class'=>'errmsg','style'=>['padding'=>'5px']]);

echo $field;

输出

<div class="widget name" style="display:block">
 <input name="name" value="" />
 <div style="color:yellow;background:red;padding:5px" class="errmsg">
    Name is required!
 </div>
</div>

请注意,在这种情况下,我们通过设置 'display' 属性来启用错误显示。

通过传递一个负数(即 false)的参数来禁用错误显示。

$field = new TextField('name');
$field->required('Name is required!')
	->context(['name'=>''])
	->error(['class'=>'errmsg','style'=>['padding'=>'5px']])
	->error(false);

echo $field;

输出

<div class="widget name" style="display:block">
 <input name="name" value="" />
 <div style="color:yellow;background:red;padding:5px" class="errmsg">
 </div>
</div>

注意:您也可以传递将 'display' 属性设置为 false 的参数。

使用 inline 选项使错误标签在同一行显示。

$field = new TextField('name');
$field->required('Name is required!')
	->context(['name'=>''])
	->error(['display'=>true,'inline'=>true]);

echo $field;

输出

<div class="widget name" style="display:block">
 <input name="name" value="" />
 <div style="color:yellow;background:red;display:inline-block;margin-right:10px" class="error">
    Name is required!
 </div>
</div>

指定默认值

您可以为字段留空和/或发生验证错误时使用的情况设置一个默认值。

$field = new TextField('amount');
$field->fallback(1);

echo $field;

输出

<div class="widget amount" style="display:block">
 <input id="amount" name="amount" value="1" />
 <div style="color:yellow;background:red" class="error">
 </div>
</div>