额外的用户界面功能
Introduction
使用 Snowboard 框架时,您可以选择指定extras
包含额外 UI 功能的标志。在前端 CMS 页面中处理 AJAX 请求时,这些功能通常很有用。
{% snowboard extras %}
加载指示器
加载指示器是在 AJAX 请求运行时显示在页面顶部的加载栏。该指标挂钩到全球事件 由 Snowboard 框架使用。
当 AJAX 请求开始时,ajaxPromise
事件被触发。这会在页面顶部显示加载指示器。解决此承诺后,将删除加载栏。
加载按钮
当任何元素包含data-attach-loading
属性,CSS类wn-loading
将在 AJAX 请求期间添加到其中。这个类会产生一个加载微调器 在按钮和锚元素上使用:after
CSS 选择器。
<form data-request="onSubmit">
<button data-attach-loading>
Submit
</button>
</form>
<a
href="#"
data-request="onDoSomething"
data-attach-loading>
Do something
</a>
闪讯
指定data-request-flash
表单上的属性,以便在成功的 AJAX 请求上启用 flash 消息。
<form
data-request="onSuccess"
data-request-flash>
<!-- ... -->
</form>
结合使用Flash
facade 在事件处理程序中,请求完成后将出现一条闪现消息。
function onSuccess()
{
Flash::success('You did it!');
}
使用 AJAX Flash 消息时,您还应确保您的主题支持标准快讯 通过将以下代码放置在您的页面或布局中,以便在页面加载时呈现尚未显示的 Flash 消息。
{% flash %}
<p
data-control="flash-message"
class="flash-message fade"
data-flash-type="{{ type }}"
data-flash-duration="5">
{{ message }}
</p>
{% endflash %}
也可以通过 Snowboard 从您的 JavaScript 文件中调用 Flash 消息。
Snowboard.flash(
'This is a flash message', // message, as a string
'info', // flash type, as a string - one of "info", "default", "success", "warning" or "error"
7 // duration (seconds), as an integer. Set to 0 to keep flash message until clicked on.
);
表单验证
您可以指定data-request-validate
表单上的属性以启用具有字段和表单的服务器端验证功能。
<form
data-request="onSubmit"
data-request-validate>
<!-- ... -->
</form>
抛出验证错误
在服务器端 AJAX 处理程序中,您可以抛出一个验证异常 使用ValidationException
使字段无效的类。应该为异常提供一个数组,其中说明键的字段名称和值的错误消息。
function onSubmit()
{
throw new ValidationException(['name' => 'You must give a name!']);
}
NOTE: 你也可以通过Validator instance 作为异常的第一个参数,以使用内置的验证服务。
显示错误信息
在表单内,您可以使用data-validate-error
容器元素上的属性。容器内的内容将设置为错误消息,元素将变为可见。
<div data-validate-error></div>
要显示多条错误消息,请包含一个带有data-message
属性。在此示例中,段落标签将被复制并设置为每条存在的消息的内容。
<div class="alert alert-danger" data-validate-error>
<p data-message></p>
</div>
这handleValidationErrors
回调,以及ajaxValidationErrors
全局事件,可与请求API 允许您完全自定义客户端验证处理。这handleValidationErrors
回调可用于控制每个请求的验证,而ajaxValidationErrors
全局事件可以被使用滑雪板插件 以全球方式增强客户端验证。
显示字段错误
或者,您可以通过定义一个使用data-validate-for
属性,将字段名称作为值传递。
<!-- Input field -->
<input name="phone" />
<!-- Validation message for the field -->
<div data-validate-for="phone"></div>
如果该元素留空,它将使用来自服务器的验证文本填充。否则你可以指定任何你喜欢的文本,它会被显示出来。
<div data-validate-for="phone">
Oops.. phone number is invalid!
</div>
使用示例
下面是一个完整的表单验证示例。它调用了onDoSomething
触发加载提交按钮的事件处理程序,对表单字段执行验证,然后显示一条成功的快速消息。
<form
data-request="onDoSomething"
data-request-validate
data-request-flash>
<div>
<input name="name" />
<span data-validate-for="name"></span>
</div>
<div>
<input name="email" />
<span data-validate-for="email"></span>
</div>
<button data-attach-loading>
Submit
</button>
<div class="alert alert-danger" data-validate-error>
<p data-message></p>
</div>
</form>
AJAX 事件处理程序查看客户端发送的 POST 数据并将一些规则应用于验证器。如果验证失败,一个ValidationException
被抛出,否则Flash::success
消息被返回。
function onDoSomething()
{
$data = post();
$rules = [
'name' => 'required',
'email' => 'required|email',
];
$validation = Validator::make($data, $rules);
if ($validation->fails()) {
throw new ValidationException($validation);
}
Flash::success('Jobs done!');
}
资产加载器
Snowboard extras 中包含一个资产加载器,允许使用 JavaScript 在页面内简单地加载资产。此加载器还允许组件在响应 AJAX 请求时将资产注入您的 CMS 页面,从而允许资产延迟到需要时使用。
Asset Loader 插件在 Snowboard 中注册为assetLoader
单例。
可以通过资产加载器加载以下资产:
-
JavaScript 文件: 这些文件将被预加载并注入到页面中,在结束 body 标记之前 (
</body>
). -
CSS 样式表: 这些文件将被预加载并注入到页面中,在结束 head 标记之前 (
</head>
) - Images: 这些文件将被预加载,但不会被注入到页面中,使其可用作可能显示在组件标记中的图像的图像预加载器。
默认情况下,Asset Loader 将简单地侦听在其响应中包含资产的 AJAX 请求,并将根据需要自动为您加载和填充这些资产。但是,您也可以使用此加载器根据需要手动注入资产:
Snowboard.assetLoader().load({
js: [
// URLs of JavaScript files to load, as an array
],
css: [
// URLs of CSS stylesheet files to load, as an array
],
img: [
// URLs of images to pre-load, as an array
]
});
Asset Loader 将确保资产只加载一次——任何对同一资产的重复请求都将被忽略。
资产加载器会触发两个事件,具体取决于资产是否成功加载:
Event | Promise? | Parameters | Description |
---|---|---|---|
assetLoader.loaded |
No | (String) type, (String) asset, (HTMLElement) assetElement |
当资产成功加载并注入页面时调用。第一个参数将是资产类型(其中之一script ,style 或者image ,第二个参数将是资产的 URL,第三个参数将是注入资产的 HTML 元素。 |
assetLoader.error |
No | (String) type, (String) asset, (HTMLElement) assetElement |
当资产加载失败时调用。参数是一样的loaded 事件,因为资产将被注入以触发资产的加载。 |
数据配置
包含 Winter 小部件和 Snowboard 插件配置的常见方法是为元素提供代表配置选项和值的数据属性标签。 Snowboard 包括一个带有 extras 包的数据配置插件,允许您从元素的数据属性中快速提取特定插件的配置。
这允许您将配置从 PHP 端(例如组件的配置文件)传递到部分 HTML,然后可以由 JavaScript 端的相应 Snowboard 插件读取,从而允许用户完全操纵小部件的配置和体验通过Winter后端。
Example
比方说,您有一个图库组件,它有一些配置选项,您可以在使用该组件时将这些选项传递给页面:
namespace Acme\Gallery\Components;
class Gallery extends \Cms\Classes\ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Gallery',
'description' => 'My ultra-cool gallery component',
];
}
public function defineProperties()
{
return [
'numImages' => [
'title' => 'Number of images',
'type' => 'dropdown',
'default' => 3,
'options' => [
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
]
],
'showCaption' => [
'title' => 'Show caption?',
'type' => 'checkbox'
'default' => true,
],
];
}
public function settings()
{
return [
'numImages' => $this->property('numImages', 3),
'showCaption' => $this->property('showCaption', true) ? 'true' : 'false',
];
}
}
然后您可能有一个默认(或覆盖)部分,其中包含将由您的 Snowboard 插件使用的 HTML。
<div
class="gallery"
data-gallery
data-num-images="{{ __SELF__.settings().numImages }}"
data-show-caption="{{ __SELF__.settings().showCaption }}"
>
<img src="picture-1.png" title="This is a cool picture">
<img src="picture-2.png" title="This is another cool picture">
<img src="picture-3.png" title="Look at this">
<img src="picture-4.png" title="Wow, so cool!">
<img src="picture-5.png" title="Nice!">
</div>
有了这个,您的 Snowboard 插件现在可以直接从后端使用配置初始化画廊。
class Gallery extends Snowboard.PluginBase {
constructor(snowboard, element) {
super(snowboard);
this.element = element;
// Initialise the configuration, and make it available in the plugin as "this.config"
this.config = this.snowboard.dataConfig(this, element);
this.createGallery();
}
defaults() {
return {
numImages: 5,
showCaption: false,
};
}
createGallery() {
const numImages = this.config.get('numImages'); // Will return 3 since the attribute has been set by the default value defined in the PHP component class
const showCaption = this.config.get('showCaption'); // Will be true, since the attribute has been set by the default value defined in the PHP component class
}
}
按照这种结构,您可以对组件的体验进行全栈控制,从而提供一种从后端控制前端小部件的简单机制。
Usage
数据配置功能在 Snowboard 中注册为dataConfig
插件,可以用初始化this.snowboard.dataConfig()
.
初始化数据配置需要两个参数,您希望配置可用的 Snowboard 插件,以及从中提取数据配置的 HTML 元素。第三个参数也可用于从 JavaScript 端分配本地定义的配置覆盖。
this.config = this.snowboard.dataConfig(
this, // Add the config to the current instance
element, // HTML element to get the config values from
localConfig, // (optional) Locally-defined JavaScript config overrides
);
通过将其填充到插件变量中,您可以在整个插件中使用它。
NOTE: 配置键(即来自数据属性名称的名称)遵循名称转换 HTML 元素数据集的方法。这意味着,一般来说,名称将被转换为“camelCase”而没有
data-
字首。在上面的例子中,data-num-images
转换为numImages
在 JavaScript 端的配置中。
在确定可用的配置选项时,数据配置将寻找一个defaults
插件实例中的方法。此方法必须返回一个对象,该对象将接受的配置选项作为对象键,并将这些选项的默认值作为对象值。
class Gallery extends Snowboard.PluginBase {
// ...
defaults() {
return {
numImages: 5,
showCaption: false,
};
}
// ...
}
在上面的示例中,这将允许data-num-images
和data-show-caption
给定元素中的属性来填充配置,但是,如果另一个数据属性(例如data-allow-zoom
)被添加,这将not 可作为配置选项使用。
如果您想接受任何数据属性作为配置值,您可以改为向名为的插件实例添加一个属性acceptAllDataConfigs
价值为true
.
class Gallery extends Snowboard.PluginBase {
constructor(snowboard, this, element) {
super(snowboard);
this.element = element;
this.acceptAllDataConfigs = true;
this.config = this.snowboard.dataConfig(this, element);
}
// ...
}
数据配置构造的第三个参数允许您使用 JavaScript 定义配置值覆盖。如果您希望在确定组件的最终配置时包含另一种配置机制,这将很有用。例如,上面的 Gallery 示例可能允许人们显示更多或更少来自用户设置页面的图像。
class Gallery extends Snowboard.PluginBase {
constructor(snowboard, this, element, userNumImages) {
super(snowboard);
this.element = element;
this.acceptAllDataConfigs = true;
const localConfig = {
numImages: userNumImages
};
this.config = this.snowboard.dataConfig(this, element, localConfig);
}
// ...
}
在上面的例子中,即使 gallery 元素定义了一个data-num-images
数据属性,这将被覆盖userNumImages
用于构建图库的参数。这userNumImages
参数可以由用户配置源填充。
Methods
返回的配置实例this.snowboard.config(bindTo, elementFrom)
提供了以下方法:
get()
将整个配置作为对象获取,配置名称作为对象键,值作为对象值。该对象将由默认值组成,并与优先的数据属性值合并在一起。
this.config.get(); // Returns an object of all configuration options and their values.
get(configName: string)
获取给定配置名称的配置值。这将首先从本地配置中检索,然后是提供配置的元素的数据属性,最后如果未在元素上指定,则从默认值中检索。
如果已经为配置提供了配置名称的本地配置值,它将通过所有其他来源返回。
这将返回undefined
如果元素的数据属性中没有配置值,本地配置或默认值。
this.config.get('configKey'); // Returns the value of one configuration option.
set(configName: string, configValue: any, persist: boolean)
在运行时为给定的配置名称设置配置值。这将作为覆盖 - 它将替换数据配置和配置选项的任何默认值。
默认情况下,此覆盖不会持续存在 - 如果刷新数据配置,它将再次被数据属性值或默认值替换。如果第三个参数persist
被设定为true
,这个值会被持久化,即使刷新也会保留。
this.config.set('configKey', 'new value');
this.config.get('configKey'); // Returns "new value".
refresh()
刷新整个配置。这将再次使用数据属性配置、本地配置或默认值重新填充配置。如果您允许从外部修改元素的数据属性,这将很有用。
// Assuming that "data-config-key" on the element is set to "old"
this.config.set('configKey', 'new');
this.config.get('configKey'); // Returns "new"
// Let's do a refresh
this.config.refresh();
this.config.get('configKey'); // Returns "old", as per the data attribute on the element.
// Let's persist the configuration value.
this.config.set('configKey', 'new', true);
// Another refresh
this.config.refresh();
this.config.get('configKey'); // Returns "new", as the new value was persisted.
进一步说明
配置值强制
由数据属性或通过set()
通过将所有给定内容转换为字符串并应用以下规则,方法将根据内容“强制”为变量类型:
- 一个字符串
"null"
或者"undefined"
将被解释为 JavaScriptnull
和undefined
, 分别。 - 一个字符串
"true"
或者"yes"
将被解释为布尔值true
. - 一个字符串
"false"
或者"no"
将被解释为布尔值false
. - 一个字符串前缀为
base64:
后跟 base64 编码的字符串将被解码,然后使用解码后的值进行值强制转换。 - 字符串数字将转换为 JavaScript 数字。
- 字符串最终将通过 JSON 解析器运行 - 如果解析器成功,将使用此值。
- 如果以上都失败,则字符串值将保留为字符串。
已经在 JavaScript 中定义的本地配置值不会被强制转换。
没有值的数据属性
数据配置将没有值的数据属性解释为布尔值true
,类似于复选框如何使用checked
没有值的属性使复选框被选中,或者选择选项使用selected
没有值的属性使其成为选定的选项。
在这种情况下,最好将配置选项设为默认值false
使数据属性成为一个简单的切换。