{"id":3790,"date":"2017-07-02T10:08:21","date_gmt":"2017-07-02T08:08:21","guid":{"rendered":"https:\/\/florianbrinkmann.com\/en\/?p=3790"},"modified":"2020-02-09T10:59:48","modified_gmt":"2020-02-09T09:59:48","slug":"selective-refresh-customizer","status":"publish","type":"post","link":"https:\/\/florianbrinkmann.com\/en\/selective-refresh-customizer-3790\/","title":{"rendered":"Use selective refresh in the customizer"},"content":{"rendered":"\n<p>Since WordPress 4.5, we can reload only parts of the customizer preview after a setting has changed. With that, the user has \u2014 at least \u2014 the feeling of a faster experience. And in most cases, it will be actually faster (and besides that, this feature could eliminate the customizer page and replace it with inline editing, writes Weston Ruter in his post \u00bb<a href=\"https:\/\/make.wordpress.org\/core\/2016\/02\/16\/selective-refresh-in-the-customizer\/\">Selective Refresh in the Customizer<\/a>\u00ab). Here I show you how to implement selective refresh.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Using selective refresh for a customizer setting<\/h2>\n\n\n\n<p>Using the feature with an existing customizer setting is actually quite simple. Here comes a complete example for a customizer setting from my <a href=\"https:\/\/florianbrinkmann.com\/en\/wordpress-themes\/photographus\/\">Photographus<\/a> theme:<\/p>\n\n\n<pre class=\"wp-block-code lang-php\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/**\n * Create setting for page.\n *\/<\/span>\n$wp_customize-&gt;add_setting( <span class=\"hljs-string\">\"photographus_panel_{$i}_page\"<\/span>, &#91;\n\t<span class=\"hljs-string\">'default'<\/span>           =&gt; <span class=\"hljs-keyword\">false<\/span>,\n\t<span class=\"hljs-string\">'sanitize_callback'<\/span> =&gt; <span class=\"hljs-string\">'absint'<\/span>,\n\t<span class=\"hljs-string\">'transport'<\/span>         =&gt; <span class=\"hljs-string\">'postMessage'<\/span>,\n] );\n\n<span class=\"hljs-comment\">\/**\n * Create control for page.\n *\/<\/span>\n$wp_customize-&gt;add_control( <span class=\"hljs-string\">\"photographus_panel_{$i}_page\"<\/span>, &#91;\n\t<span class=\"hljs-string\">'label'<\/span>           =&gt; __( <span class=\"hljs-string\">'Select page'<\/span>, <span class=\"hljs-string\">'photographus'<\/span> ),\n\t<span class=\"hljs-string\">'section'<\/span>         =&gt; <span class=\"hljs-string\">'photographus_options'<\/span>,\n\t<span class=\"hljs-string\">'type'<\/span>            =&gt; <span class=\"hljs-string\">'dropdown-pages'<\/span>,\n\t<span class=\"hljs-string\">'allow_addition'<\/span>  =&gt; <span class=\"hljs-keyword\">true<\/span>,\n\t<span class=\"hljs-string\">'active_callback'<\/span> =&gt; <span class=\"hljs-string\">'photographus_is_page_panel'<\/span>,\n\t<span class=\"hljs-string\">'input_attrs'<\/span>     =&gt; &#91;\n\t\t<span class=\"hljs-string\">'data-panel-number'<\/span> =&gt; $i,\n\t],\n] );\n\n$wp_customize-&gt;selective_refresh-&gt;add_partial( <span class=\"hljs-string\">\"photographus_panel_{$i}_page_partial\"<\/span>, &#91;\n\t<span class=\"hljs-string\">'selector'<\/span>            =&gt; <span class=\"hljs-string\">\"#frontpage-section-$i\"<\/span>,\n\t<span class=\"hljs-string\">'settings'<\/span>            =&gt; &#91;\n\t\t<span class=\"hljs-string\">\"photographus_panel_{$i}_page\"<\/span>,\n\t],\n\t<span class=\"hljs-string\">'render_callback'<\/span>     =&gt; <span class=\"hljs-string\">'photographus_the_page_panel'<\/span>,\n\t<span class=\"hljs-string\">'container_inclusive'<\/span> =&gt; <span class=\"hljs-keyword\">true<\/span>,\n] );<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code class=\"lang-php\">add_setting()<\/code> and <code class=\"lang-php\">add_control()<\/code> part should not be something new for you if you already worked with the customizer. Since 4.5 we can use <code class=\"lang-php\">$wp_customize-&gt;selective_refresh-&gt;add_partial<\/code>, which we hand over a unique identifier as the first param and a settings array as the second, which contains the following values:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>An HTML selector, who specifies the element which needs a reload.<\/li><li>One or more <code class=\"lang-php\">settings<\/code>, which trigger the refresh.<\/li><li>A callback function which echoes the new markup.<\/li><li>The instruction to also reload the container element in our case (<code class=\"lang-php\">#frontpage-section-$i<\/code>).<\/li><\/ul>\n\n\n\n<p>And that is it \u2014 we implemented selective refresh for a setting ? But there is one thing to notice:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Markup which is modified by JavaScript inside <code class=\"lang-php\">render_callback<\/code><\/h3>\n\n\n\n<p>If you reload an element which contains markup, which is modified by JavaScript (for example, a masonry grid), then you have to run the JavaScript on a selective refresh. The handling looks as following in my Photographus theme:<\/p>\n\n\n<pre class=\"wp-block-code lang-javascript line-numbers\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/**\n * Custom JavaScript functions for the customizer preview.\n *\n * <span class=\"hljs-doctag\">@version<\/span> 1.0.0\n *\n * <span class=\"hljs-doctag\">@package<\/span> Photographus\n *\/<\/span>\n;(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n    document.addEventListener(<span class=\"hljs-string\">'DOMContentLoaded'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n        <span class=\"hljs-comment\">\/**\n         * Selectice refresh check from https:\/\/github.com\/xwp\/wp-jetpack\/blob\/feature\/selective-refresh-widget-support\/modules\/widgets\/contact-info\/contact-info-map.js#L35\n         * <span class=\"hljs-doctag\">@type<\/span> {*}\n         *\/<\/span>\n        hasSelectiveRefresh = (\n            <span class=\"hljs-string\">'undefined'<\/span> !== typeof wp &amp;&amp;\n            wp.customize &amp;&amp;\n            wp.customize.selectiveRefresh &amp;&amp;\n            wp.customize.widgetsPreview &amp;&amp;\n            wp.customize.widgetsPreview.WidgetPartial\n        );\n        <span class=\"hljs-keyword\">if<\/span> (hasSelectiveRefresh) {\n            wp.customize.selectiveRefresh.bind(<span class=\"hljs-string\">'partial-content-rendered'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(placement)<\/span> <\/span>{\n                buildMasonryGrid(hasSelectiveRefresh);\n\n                addClassToImageLinks();\n\n                fullWidthImages();\n\n                <span class=\"hljs-comment\">\/**\n                 * Get the front page panels.\n                 * <span class=\"hljs-doctag\">@type<\/span> {NodeList}\n                 *\/<\/span>\n                <span class=\"hljs-keyword\">var<\/span> panels = document.querySelectorAll(<span class=\"hljs-string\">'.frontpage-section'<\/span>);\n                <span class=\"hljs-comment\">\/**\n                 * Check if we have panels.\n                 *\/<\/span>\n                <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-number\">0<\/span> !== panels.length) {\n                    <span class=\"hljs-keyword\">var<\/span> panelsWithContent = <span class=\"hljs-number\">0<\/span>;\n                    <span class=\"hljs-comment\">\/**\n                     * Loop through them.\n                     *\/<\/span>\n                    <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">var<\/span> i = <span class=\"hljs-number\">0<\/span>; i &lt; panels.length; i++) {\n                        <span class=\"hljs-comment\">\/**\n                         * Check if it is a panel placeholder.\n                         *\/<\/span>\n                        <span class=\"hljs-keyword\">if<\/span> (!panels&#91;i].classList.contains(<span class=\"hljs-string\">'frontpage-section-placeholder'<\/span>)) {\n                            panelsWithContent++;\n                        }\n                    }\n                    <span class=\"hljs-comment\">\/**\n                     * Refresh the preview if we have only panel placeholders, so the default homepage is displayed\n                     * correctly.\n                     *\n                     * <span class=\"hljs-doctag\">@link<\/span> https:\/\/make.xwp.co\/2015\/12\/08\/implementing-selective-refresh-in-the-customizer\/\n                     *\/<\/span>\n                    <span class=\"hljs-keyword\">if<\/span> (panelsWithContent === <span class=\"hljs-number\">0<\/span>) {\n                        wp.customize.preview.send(<span class=\"hljs-string\">'refresh'<\/span>);\n                    }\n                }\n            });\n        }\n    });\n})();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The important part is the first section up to line 22 \u2014 after that, you can call the functions to get the wanted behavior for the reloaded markup.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since WordPress 4.5, we can reload only parts of the customizer preview after a setting has changed. With that, the user has \u2014 at least \u2014 the feeling of a faster experience. And in most cases, it will be actually faster (and besides that, this feature could eliminate the customizer page and replace it with [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wpf_show_in_dewp_planet_feed":false,"flobn_post_versions":"","webmentions_disabled_pings":false,"webmentions_disabled":false,"lazy_load_responsive_images_disabled":false,"footnotes":""},"categories":[115],"tags":[],"class_list":["post-3790","post","type-post","status-publish","format-standard","hentry","category-wordpress-snippets"],"wp-worthy-pixel":{"ignored":false,"public":"c662163883a44818abd07b9e7bb72ea2","server":"vg07.met.vgwort.de","url":"https:\/\/vg07.met.vgwort.de\/na\/c662163883a44818abd07b9e7bb72ea2"},"wp-worthy-type":"normal","_links":{"self":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/3790","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/comments?post=3790"}],"version-history":[{"count":3,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/3790\/revisions"}],"predecessor-version":[{"id":5875,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/3790\/revisions\/5875"}],"wp:attachment":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/media?parent=3790"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/categories?post=3790"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/tags?post=3790"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}