[wp-trac] [WordPress Trac] #33507: Allow widget controls to be JS-driven

WordPress Trac noreply at wordpress.org
Thu Jan 28 16:25:15 UTC 2016


#33507: Allow widget controls to be JS-driven
-------------------------+--------------------------------------
 Reporter:  westonruter  |       Owner:  westonruter
     Type:  enhancement  |      Status:  accepted
 Priority:  normal       |   Milestone:  Future Release
Component:  Widgets      |     Version:  3.9
 Severity:  normal       |  Resolution:
 Keywords:               |     Focuses:  javascript, performance
-------------------------+--------------------------------------

Old description:

> Widgets currently have an almost complete reliance on PHP for all aspects
> of their behavior:
>
> * Generating the control form via `WP_Widget::form()`
> * Validating the instance data via `WP_Widget::update()`
> * Rendering the widget into the template via `WP_Widget::widget()`
>
> The dependence on PHP can make managing widgets in WordPress relatively
> slow. In the Customizer, it can be excruciatingly slow since the widget
> form control is presented alongside the widget in the preview, and so the
> slow roundtrip time for sanitization and rendering is clear (especially
> with full-page refreshes of the Customizer, which is to be mitigated in
> #27355 via partial refreshes).
>
> In the Customizer, making a change to a widget form field results in an
> `update-widget` Ajax call to pass the full form data to WordPress to pass
> it through the widget’s `update` callback for sanitization. The Ajax
> handler then passes this updated instance through the `form` callback,
> and the HTML output of the `form` callback then gets sent back in the
> Ajax response. (Look at the number of Ajax requests triggered when typing
> into a widget field.) The Customizer widget logic then tries to apply the
> sanitized instance data by aligning the input fields in the widget form
> shown in the Customizer with the input fields sent in the Ajax response.
> When the input fields are aligned (when the same inputs are present),
> then the inputs’ values will be updated to their sanitized values and a
> `widget-synced` jQuery event is triggered. But if the inputs cannot be
> aligned (which can happen easily if any of the fields are created
> dynamically), then it falls back to showing an Update button which will
> do a full replacement of the widget form, just as is done on the widgets
> admin page (and a `widget-updated` jQuery event is triggered). Then
> finally, once the widget instance is updated, then the Customizer preview
> can do its full page refresh with the widget instance previewed in the
> template.
>
> Most of the above logic can be eliminated entirely if widget controls
> handled rendering of the controls and sanitization of the instance data
> purely with JavaScript, just like every other Customizer control normally
> behaves.
>
> Widgets would hugely benefit from a revamp following patterns laid down
> in Customizer controls. Customizer controls were designed to be JS-driven
> from the start. A Customizer control gets associated with a Customizer
> setting, the control then applies the setting data onto the control’s
> template and the inputs are automatically synced back to the setting—this
> is accomplished via two-way data bindings provided by
> `wp.customize.Element`. So controls in the Customizer handle UI
> validation purely with JavaScript. There is no need for an Ajax request
> because the logic is in the client. (True this means that the
> sanitization logic has to be duplicated in PHP and JS, but this can be
> minimized by adopting a common schema for the input types.)
>
> Naturally these new JS-driven widgets would need to be backwards
> compatible with existing widgets. We can allow a widget to opt-in to
> indicate it is JS-driven by supplying a new flag to  the seldom-used
> `$control_options` param to `WP_Widget::__construct()` (which is used to
> pass the infamous width/height for wide widget form controls), for
> example:
>
> When this is present, the Customizer would disable the existing update
> mechanism and defer to the control’s own logic.
>
> Note that these new JS-driven widget controls in the Customizer would be
> implemented in a very similar way to how nav menu item controls have been
> implemented in the Customizer in 4.3. The overall widget control would be
> associated with a single widget instance setting. The widget’s setting
> would be just the JSON-serializable instance array (object) as opposed to
> a scalar value, and each property in the setting value would then get
> mapped to a different `wp.customize.Element` in the widget control: the
> inputs’ values would then get synced back into property of the setting
> object value by means of `wp.customize.Element` instances.
>
> Some widget controls would still depend on the server for UI validation,
> for instance the RSS widget. However, only specific fields would need to
> be validated as opposed to the entire form. Note again that full server-
> side validation of the widget instance data would still be required.
> Ideally the duplication of logic here could be reduced by having a schema
> that both the JS and PHP validation logic could read from.
>
> While the above focuses specifically on making the `WP_Widget::form()`
> and `WP_Widget::update()` both JS-driven, there may also be an
> opportunity to allow widgets to opt-in to JS-driven rendering of a given
> widget (i.e. implementing `WP_Widget::widget()`, in JS). This would make
> a lot of sense if the widget defined its template in Mustache (or Twig)
> and then allowed the instance array to be applied to that template either
> server-side or client-side. The effect for client-side would be
> postMessage instant previews of changes to widgets in the Customizer. The
> PHP-driven performant alternative to this would be partial-refresh as
> outlined in #27355.
>
> By using JS-driven widgets, we will be able to use control templates for
> the widget controls as opposed to having to include a separate copy of
> the widget form with each control's params. This can drastically reduce
> the page weight, since the control template only needs to be included
> once.
>
> By implementing JS-driven widget controls, the user experience of
> managing widgets would be vastly improved and the server load would be
> greatly reduced.

New description:

 Widgets currently have an almost complete reliance on PHP for all aspects
 of their behavior:

 * Generating the control form via `WP_Widget::form()`
 * Validating the instance data via `WP_Widget::update()`
 * Rendering the widget into the template via `WP_Widget::widget()`

 The dependence on PHP can make managing widgets in WordPress relatively
 slow. In the Customizer, it can be excruciatingly slow since the widget
 form control is presented alongside the widget in the preview, and so the
 slow roundtrip time for sanitization and rendering is clear (especially
 with full-page refreshes of the Customizer, which is to be mitigated in
 #27355 via partial refreshes).

 In the Customizer, making a change to a widget form field results in an
 `update-widget` Ajax call to pass the full form data to WordPress to pass
 it through the widget’s `update` callback for sanitization. The Ajax
 handler then passes this updated instance through the `form` callback, and
 the HTML output of the `form` callback then gets sent back in the Ajax
 response. (Look at the number of Ajax requests triggered when typing into
 a widget field.) The Customizer widget logic then tries to apply the
 sanitized instance data by aligning the input fields in the widget form
 shown in the Customizer with the input fields sent in the Ajax response.
 When the input fields are aligned (when the same inputs are present), then
 the inputs’ values will be updated to their sanitized values and a
 `widget-synced` jQuery event is triggered. But if the inputs cannot be
 aligned (which can happen easily if any of the fields are created
 dynamically), then it falls back to showing an Update button which will do
 a full replacement of the widget form, just as is done on the widgets
 admin page (and a `widget-updated` jQuery event is triggered). Then
 finally, once the widget instance is updated, then the Customizer preview
 can do its full page refresh with the widget instance previewed in the
 template.

 Most of the above logic can be eliminated entirely if widget controls
 handled rendering of the controls and sanitization of the instance data
 purely with JavaScript, just like every other Customizer control normally
 behaves.

 Widgets would hugely benefit from a revamp following patterns laid down in
 Customizer controls. Customizer controls were designed to be JS-driven
 from the start. A Customizer control gets associated with a Customizer
 setting, the control then applies the setting data onto the control’s
 template and the inputs are automatically synced back to the setting—this
 is accomplished via two-way data bindings provided by
 `wp.customize.Element`. So controls in the Customizer handle UI validation
 purely with JavaScript. There is no need for an Ajax request because the
 logic is in the client. (True this means that the sanitization logic has
 to be duplicated in PHP and JS, but this can be minimized by adopting a
 common schema for the input types.)

 Naturally these new JS-driven widgets would need to be backwards
 compatible with existing widgets. We can allow a widget to opt-in to
 indicate it is JS-driven by supplying a new flag to  the seldom-used
 `$control_options` param to `WP_Widget::__construct()` (which is used to
 pass the infamous width/height for wide widget form controls), for
 example:

 When this is present, the Customizer would disable the existing update
 mechanism and defer to the control’s own logic.

 Note that these new JS-driven widget controls in the Customizer would be
 implemented in a very similar way to how nav menu item controls have been
 implemented in the Customizer in 4.3. The overall widget control would be
 associated with a single widget instance setting. The widget’s setting
 would be just the JSON-serializable instance array (object) as opposed to
 a scalar value, and each property in the setting value would then get
 mapped to a different `wp.customize.Element` in the widget control: the
 inputs’ values would then get synced back into property of the setting
 object value by means of `wp.customize.Element` instances.

 Some widget controls would still depend on the server for UI validation,
 for instance the RSS widget. However, only specific fields would need to
 be validated as opposed to the entire form. Note again that full server-
 side validation of the widget instance data would still be required.
 Ideally the duplication of logic here could be reduced by having a schema
 that both the JS and PHP validation logic could read from.

 While the above focuses specifically on making the `WP_Widget::form()` and
 `WP_Widget::update()` both JS-driven, there may also be an opportunity to
 allow widgets to opt-in to JS-driven rendering of a given widget (i.e.
 implementing `WP_Widget::widget()`, in JS). This would make a lot of sense
 if the widget defined its template in Mustache (or Twig) and then allowed
 the instance array to be applied to that template either server-side or
 client-side. The effect for client-side would be postMessage instant
 previews of changes to widgets in the Customizer. The PHP-driven
 performant alternative to this would be partial-refresh as outlined in
 #27355.

 By using JS-driven widgets, we will be able to use control templates for
 the widget controls as opposed to having to include a separate copy of the
 widget form with each control's params. This can drastically reduce the
 page weight, since the control template only needs to be included once.

 By implementing JS-driven widget controls, the user experience of managing
 widgets would be vastly improved and the server load would be greatly
 reduced.

 Depends on #35574 (Add REST API JSON schema information to WP_Widget)

--

Comment (by westonruter):

 Dependency: #35574 (Add REST API JSON schema information to WP_Widget)

--
Ticket URL: <https://core.trac.wordpress.org/ticket/33507#comment:12>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list