-
Notifications
You must be signed in to change notification settings - Fork 106
/
Control.php
183 lines (154 loc) · 5.13 KB
/
Control.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?php
declare(strict_types=1);
namespace Atk4\Ui\Form;
use Atk4\Data\Field;
use Atk4\Data\Model;
use Atk4\Data\Model\EntityFieldPair;
use Atk4\Ui\Exception;
use Atk4\Ui\Form;
use Atk4\Ui\View;
/**
* Provides generic functionality for a form control.
*/
class Control extends View
{
/** @var Form to which this field belongs */
public $form;
/** @var EntityFieldPair<Model, Field> */
public $entityField;
/** @var string */
public $controlClass = '';
/** @var bool Whether you need this field to be rendered wrap in a form layout or as his */
public $layoutWrap = true;
/** @var bool rendered or not input label in generic Form\Layout template. */
public $renderLabel = true;
public $width;
/**
* Caption is a text that must appear somewhere nearby the field. For a form with layout, this
* will typically place caption above the input field, but for checkbox this may appear next to the
* checkbox itself. If Form Layout does not have captions above the input field, then caption
* will appear as a placeholder of the input fields and it may also appear as a tooltip.
*
* Caption is usually specified by a model.
*
* @var string
*/
public $caption;
/**
* Placed as a pointing label below the field. This only works when Form\Control appears in a form. You can also
* set this to object, such as \Atk4\Ui\Text otherwise HTML characters are escaped.
*
* @var string|\Atk4\Ui\View|array
*/
public $hint;
/**
* Is input field disabled?
* Disabled input fields are not editable and will not be submitted.
*
* @var bool
*/
public $disabled = false;
/**
* Is input field read only?
* Read only input fields are not editable, but will be submitted.
*
* @var bool
*/
public $readonly = false;
protected function init(): void
{
parent::init();
if ($this->form && $this->entityField) {
if (isset($this->form->controls[$this->entityField->getFieldName()])) {
throw (new Exception('Form already has a field with the same name'))
->addMoreInfo('name', $this->entityField->getFieldName());
}
$this->form->controls[$this->entityField->getFieldName()] = $this;
}
}
/**
* Sets the value of this field. If field is a part of the form and is associated with
* the model, then the model's value will also be affected.
*
* @param mixed $value
* @param mixed $junk
*
* @return $this
*/
public function set($value = null, $junk = null)
{
if ($this->entityField) {
$this->entityField->set($value);
return $this;
}
$this->content = $value;
return $this;
}
/**
* It only makes sense to have "name" property inside a field if
* it was used inside a form.
*/
protected function renderView(): void
{
if ($this->form) {
$this->template->trySet('name', $this->shortName);
}
parent::renderView();
}
protected function renderTemplateToHtml(string $region = null): string
{
$output = parent::renderTemplateToHtml($region);
/** @var Form|null $form */
$form = $this->getClosestOwner($this, Form::class);
return $form !== null ? $form->fixFormInRenderedHtml($output) : $output;
}
/**
* Shorthand method for on('change') event.
* Some input fields, like Calendar, could call this differently.
*
* If $expr is string or JsExpression, then it will execute it instantly.
* If $expr is callback method, then it'll make additional request to webserver.
*
* Could be preferable to set useDefault to false. For example when
* needing to clear form error or when form canLeave property is false.
* Otherwise, change handler will not be propagate to all handlers.
*
* Examples:
* $control->onChange('console.log("changed")');
* $control->onChange(new \Atk4\Ui\JsExpression('console.log("changed")'));
* $control->onChange('$(this).parents(".form").form("submit")');
*
* @param string|\Atk4\Ui\JsExpression|array|\Closure $expr
* @param array|bool $default
*/
public function onChange($expr, $default = [])
{
if (is_string($expr)) {
$expr = new \Atk4\Ui\JsExpression($expr);
}
if (is_bool($default)) {
$default['preventDefault'] = $default;
$default['stopPropagation'] = $default;
}
$this->on('change', '#' . $this->name . '_input', $expr, $default);
}
/**
* Method similar to View::js() however will adjust selector
* to target the "input" element.
*
* $field->jsInput(true)->val(123);
*
* @return \Atk4\Ui\Jquery
*/
public function jsInput($when = null, $action = null)
{
return $this->js($when, $action, '#' . $this->name . '_input');
}
/**
* @return string
*/
public function getControlClass()
{
return $this->controlClass;
}
}