v1.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace zin;
  3. require_once dirname(__DIR__) . DS . 'formlabel' . DS . 'v1.php';
  4. require_once dirname(__DIR__) . DS . 'control' . DS . 'v1.php';
  5. require_once dirname(__DIR__) . DS . 'content' . DS . 'v1.php';
  6. require_once dirname(__DIR__) . DS . 'input' . DS . 'v1.php';
  7. /**
  8. * 表单控件组部件。
  9. * Form control group widget.
  10. */
  11. class formGroup extends wg
  12. {
  13. /**
  14. * @var mixed[]
  15. */
  16. protected static $defineProps = array(
  17. 'id?: string', // ID。
  18. 'name?: string', // 字段名,可能影响到表单提交的域名称,如果是多个值的表单控件,可能需要将名称定义为 `key[]` 的形式。
  19. 'data?: array', // 数据属性。
  20. 'label?: string|bool', // 标签文本。
  21. 'labelFor?: string', // 标签的 for 属性。
  22. 'labelClass?: string', // 标签的 class 属性。
  23. 'labelProps?: string', // 标签的其它属性。
  24. 'labelWidth?: int|string', // 标签的宽度。
  25. 'labelHint?: string', // 标签的提示文本。
  26. 'labelHintIcon?: string="help"', // 标签的提示图标。
  27. 'labelHintClass?: string', // 标签的提示 class 属性。
  28. 'labelHintProps?: array', // 标签的提示其它属性。
  29. 'labelActions?: array', // 标签的操作按钮。
  30. 'labelActionsClass?: string', // 标签的操作按钮 class 属性。
  31. 'labelActionsProps?: array', // 标签的操作按钮其它属性。
  32. 'labelControl?: array', // 自定义标签控件。
  33. 'checkbox?: bool|array', // 标签的复选框属性定义。
  34. 'required?:bool|string="auto"', // 是否必填。
  35. 'requiredFields?: string', // 必填字段列表,例如 `'product,branch'`。
  36. 'tip?: string', // 提示文本。
  37. 'tipClass?: string|array', // 提示 class 属性。
  38. 'tipProps?: array', // 提示其它属性。
  39. 'control?: array|string', // 表单控件类型或控件属性定义。
  40. 'width?: string', // 界面宽度。
  41. 'strong?: bool', // 是否加粗。
  42. 'value?: string|array', // 值。
  43. 'disabled?: bool', // 是否禁用。
  44. 'readonly?: bool', // 是否只读。
  45. 'multiple?: bool', // 是否多选。
  46. 'hidden?: bool', // 是否隐藏。
  47. 'items?: array', // 选项列表。
  48. 'placeholder?: string', // 占位符。
  49. 'foldable?: bool', // 是否可折叠。
  50. 'pinned?: bool', // 是否固定。
  51. 'wrapBefore?: bool', // 是否在前方换行。
  52. 'wrapAfter?: bool', // 是否在后方换行。
  53. 'children?: array|object' // 内部自定义内容。
  54. );
  55. /**
  56. * @var mixed[]
  57. */
  58. protected static $controlExtendProps = array('required', 'name', 'value', 'disabled', 'items', 'placeholder', 'readonly', 'multiple');
  59. /**
  60. * @var bool
  61. */
  62. protected $isHiddenField = false;
  63. protected function created()
  64. {
  65. $required = $this->prop('required');
  66. if($required === 'auto')
  67. {
  68. $children = $this->children();
  69. $requiredFields = $this->prop('requiredFields');
  70. if($this->hasProp('name')) $required = isFieldRequired($this->prop('name'), $requiredFields);
  71. else if($children)
  72. {
  73. $required = false;
  74. foreach($children as $child)
  75. {
  76. if($child instanceof node && $child->hasProp('name') && isFieldRequired($child->prop('name'), $requiredFields)) $required = true;
  77. }
  78. }
  79. else $required = false;
  80. $this->setProp('required', $required);
  81. }
  82. }
  83. /**
  84. * @return \zin\node|\zin\set
  85. */
  86. protected function buildLabel()
  87. {
  88. list($name, $label, $labelFor, $labelClass, $labelProps, $labelHint, $labelHintClass, $labelHintProps, $labelHintIcon, $labelActions, $labelActionsClass, $labelActionsProps, $checkbox, $required, $strong, $labelControl) = $this->prop(array('name', 'label', 'labelFor', 'labelClass', 'labelProps', 'labelHint', 'labelHintClass', 'labelHintProps', 'labelHintIcon', 'labelActions', 'labelActionsClass', 'labelActionsProps', 'checkbox', 'required', 'strong', 'labelControl'));
  89. if(is_null($label) || $label === false) return setClass('no-label');
  90. if($labelControl instanceof setting) $labelControl = $labelControl->toArray();
  91. return new formLabel
  92. (
  93. set::className($labelClass, $strong ? 'font-bold' : null),
  94. set::required($required),
  95. set::hint($labelHint),
  96. set::hintIcon($labelHintIcon),
  97. set::hintClass($labelHintClass),
  98. set::hintProps($labelHintProps),
  99. set::actions($labelActions),
  100. set::actionsClass($labelActionsClass),
  101. set::actionsProps($labelActionsProps),
  102. set::checkbox($checkbox),
  103. set::text($label),
  104. set('for', is_null($labelFor) ? $name : $labelFor),
  105. set($labelProps),
  106. $labelControl ? new content(is_array($labelControl) ? set($labelControl) : $labelControl) : null
  107. );
  108. }
  109. protected function buildControl()
  110. {
  111. $control = $this->prop('control');
  112. if($control instanceof node) return $control;
  113. if(!is_string($control) && is_callable($control, true)) return $control($this->props->toJSON());
  114. if(is_string($control)) $control = array('control' => $control);
  115. elseif($control instanceof item) $control = $control->props->toJSON();
  116. elseif(is_object($control)) $control = get_object_vars($control);
  117. elseif(is_null($control) && $this->hasProp('name')) $control = array();
  118. if(!is_array($control)) return null;
  119. if($this->hasProp('id') && !isset($control['id'])) $control['id'] = '';
  120. foreach(static::$controlExtendProps as $controlPropName)
  121. {
  122. $controlPropValue = $this->prop($controlPropName);
  123. if($controlPropValue !== null && !isset($control[$controlPropName])) $control[$controlPropName] = $controlPropValue;
  124. }
  125. if(isset($control['control']) && $control['control'] === 'hidden')
  126. {
  127. unset($control['control']);
  128. $this->isHiddenField = true;
  129. return new input(set::type('hidden'), set($control));
  130. }
  131. $controlView = new control(set($control));
  132. return $controlView;
  133. }
  134. protected function buildTip()
  135. {
  136. list($tip, $tipClass, $tipProps) = $this->prop(array('tip', 'tipClass', 'tipProps'));
  137. if(empty($tip)) return null;
  138. return div
  139. (
  140. setClass('form-tip', $tipClass),
  141. set($tipProps),
  142. $tip
  143. );
  144. }
  145. protected function build()
  146. {
  147. list($name, $labelWidth, $required, $width, $id, $hidden, $foldable, $pinned, $children, $wrapBefore, $wrapAfter, $data) = $this->prop(array('name', 'labelWidth', 'required', 'width', 'id', 'hidden', 'foldable', 'pinned', 'children', 'wrapBefore', 'wrapAfter', 'data'));
  148. $control = $this->buildControl();
  149. if($this->isHiddenField) return $control;
  150. $content = div
  151. (
  152. setClass('form-group', array('required' => $required, 'hidden' => $hidden, 'is-foldable' => $foldable, 'is-pinned' => $pinned)),
  153. zui::width($width),
  154. setID($id),
  155. setData('name', $name),
  156. setData($data),
  157. setCssVar('form-horz-label-width', $labelWidth),
  158. set($this->getRestProps()),
  159. $this->buildLabel(),
  160. $control,
  161. $children,
  162. $this->children(),
  163. $this->buildTip()
  164. );
  165. if($wrapBefore || $wrapAfter) $content = array($content);
  166. if($wrapBefore) array_unshift($content, div(setClass('form-grid-wrap'), setData('wrap-before', $name)));
  167. if($wrapAfter) array_push($content, div(setClass('form-grid-wrap'), setData('wrap-after', $name)));
  168. return $content;
  169. }
  170. }