{"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

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 \u00bbSelective Refresh in the Customizer<\/a>\u00ab). Here I show you how to implement selective refresh.<\/p>\n\n\n\n\n\n\n\n

Using selective refresh for a customizer setting<\/h2>\n\n\n\n

Using the feature with an existing customizer setting is actually quite simple. Here comes a complete example for a customizer setting from my Photographus<\/a> theme:<\/p>\n\n\n

\/**\n * Create setting for page.\n *\/<\/span>\n$wp_customize->add_setting( \"photographus_panel_{$i}_page\"<\/span>, [\n\t'default'<\/span> => false<\/span>,\n\t'sanitize_callback'<\/span> => 'absint'<\/span>,\n\t'transport'<\/span> => 'postMessage'<\/span>,\n] );\n\n\/**\n * Create control for page.\n *\/<\/span>\n$wp_customize->add_control( \"photographus_panel_{$i}_page\"<\/span>, [\n\t'label'<\/span> => __( 'Select page'<\/span>, 'photographus'<\/span> ),\n\t'section'<\/span> => 'photographus_options'<\/span>,\n\t'type'<\/span> => 'dropdown-pages'<\/span>,\n\t'allow_addition'<\/span> => true<\/span>,\n\t'active_callback'<\/span> => 'photographus_is_page_panel'<\/span>,\n\t'input_attrs'<\/span> => [\n\t\t'data-panel-number'<\/span> => $i,\n\t],\n] );\n\n$wp_customize->selective_refresh->add_partial( \"photographus_panel_{$i}_page_partial\"<\/span>, [\n\t'selector'<\/span> => \"#frontpage-section-$i\"<\/span>,\n\t'settings'<\/span> => [\n\t\t\"photographus_panel_{$i}_page\"<\/span>,\n\t],\n\t'render_callback'<\/span> => 'photographus_the_page_panel'<\/span>,\n\t'container_inclusive'<\/span> => true<\/span>,\n] );<\/code><\/div>Code language:<\/span> PHP<\/span> (<\/span>php<\/span>)<\/span><\/small><\/pre>\n\n\n

The add_setting()<\/code> and add_control()<\/code> part should not be something new for you if you already worked with the customizer. Since 4.5 we can use $wp_customize->selective_refresh->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

  • An HTML selector, who specifies the element which needs a reload.<\/li>
  • One or more settings<\/code>, which trigger the refresh.<\/li>
  • A callback function which echoes the new markup.<\/li>
  • The instruction to also reload the container element in our case (#frontpage-section-$i<\/code>).<\/li><\/ul>\n\n\n\n

    And that is it \u2014 we implemented selective refresh for a setting ? But there is one thing to notice:<\/p>\n\n\n\n

    Markup which is modified by JavaScript inside render_callback<\/code><\/h3>\n\n\n\n

    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

    \/**\n * Custom JavaScript functions for the customizer preview.\n *\n * @version<\/span> 1.0.0\n *\n * @package<\/span> Photographus\n *\/<\/span>\n;(function<\/span> ()<\/span> <\/span>{\n document.addEventListener('DOMContentLoaded'<\/span>, function<\/span> ()<\/span> <\/span>{\n \/**\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 * @type<\/span> {*}\n *\/<\/span>\n hasSelectiveRefresh = (\n 'undefined'<\/span> !== typeof wp &&\n wp.customize &&\n wp.customize.selectiveRefresh &&\n wp.customize.widgetsPreview &&\n wp.customize.widgetsPreview.WidgetPartial\n );\n if<\/span> (hasSelectiveRefresh) {\n wp.customize.selectiveRefresh.bind('partial-content-rendered'<\/span>, function<\/span> (placement)<\/span> <\/span>{\n buildMasonryGrid(hasSelectiveRefresh);\n\n addClassToImageLinks();\n\n fullWidthImages();\n\n \/**\n * Get the front page panels.\n * @type<\/span> {NodeList}\n *\/<\/span>\n var<\/span> panels = document.querySelectorAll('.frontpage-section'<\/span>);\n \/**\n * Check if we have panels.\n *\/<\/span>\n if<\/span> (0<\/span> !== panels.length) {\n var<\/span> panelsWithContent = 0<\/span>;\n \/**\n * Loop through them.\n *\/<\/span>\n for<\/span> (var<\/span> i = 0<\/span>; i < panels.length; i++) {\n \/**\n * Check if it is a panel placeholder.\n *\/<\/span>\n if<\/span> (!panels[i].classList.contains('frontpage-section-placeholder'<\/span>)) {\n panelsWithContent++;\n }\n }\n \/**\n * Refresh the preview if we have only panel placeholders, so the default homepage is displayed\n * correctly.\n *\n * @link<\/span> https:\/\/make.xwp.co\/2015\/12\/08\/implementing-selective-refresh-in-the-customizer\/\n *\/<\/span>\n if<\/span> (panelsWithContent === 0<\/span>) {\n wp.customize.preview.send('refresh'<\/span>);\n }\n }\n });\n }\n });\n})();<\/code><\/div>Code language:<\/span> PHP<\/span> (<\/span>php<\/span>)<\/span><\/small><\/pre>\n\n\n

    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":"

    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 […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","wpf_show_in_dewp_planet_feed":false,"flobn_post_versions":"","lazy_load_responsive_images_disabled":false},"categories":[115],"tags":[],"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"}],"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}]}}