1

I'm trying to create Wordpress Customizer bindings based on dynamic ID's, like this

for (var i=0; i < myarray.length; i++) {
    wp.customize( 'custom_width_'+ myarray[i], function( value ) {
        value.bind( function( to ) {
            $( '#'+myarray[i] ).css( 'min-width', to );
        });
    });     
}

The code is a something I pilfered from the twentyseventeen theme (customize-preview.js) then wrapped in a loop

The problem is that myarray[] is being annihilated inside wp.customize()

Javascript experts would be amused to know I've spent hours trying to solve this.

I know I could... (kludge alert) store the ID temporarily in the DOM, but there is doubtlessly a better way.

2

the issue that you are experiencing is caused by the fact that you are using the same i variable within the full scope of the snippet.

Initially you are concatenating the variable with 'custom_width_' as a string, which is correct. At the moment of concatenation i has the correct value, which means that the setting ID you need is generated properly.

When the loop is finished, i contains the index of the last element in your array and that's exactly what is confusing you, since '#'+myarray[i] will always point to the last element in the array. The reason for this is that the callback for the customizer setting change is asynchronous. This means that even though the function appears to be within the loop (physically), it's actually not executed in the same order.

To avoid the issue, you need to declare a different scope for the variable, where it would not get mutated by the loop. The simplest way to do this is to introduce the scope by a new, anonymous function like this:

for (var i=0; i < myarray.length; i++) {
    (function( i ) {
        wp.customize( 'custom_width_'+ myarray[i], function( value ) {
            value.bind( function( to ) {
                $( '#'+myarray[i] ).css( 'min-width', to );
            });
        });     
    })( i );
}

Since i is not an object, when you use it as the parameter for a function, it's value will be copied instead of given as a reference, therefore allowing you to modify the original without affecting the clone/copy.

A slightly better-looking way to do it would be to use jQuery's each method for the loop:

$.each( myarray, function( i, id ) {
    wp.customize( 'custom_width_' + id, function( setting ) {
        setting.bind( function( value ) {
            $( '#' + id ).css( 'min-width', value );
        });
    });
});

I hope that this resolves your issue and answers your question.

  • 1
    Wow, so obvious! Perfectly answered, thanks Radoslav. I'd vote up if I could. – Konker May 25 '17 at 2:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.