1

I have the following code:

$(document).on('change', 'input.authority-email', function() {

    var authorityValues = $(this);

    var authorityArray = [].map.call(authorityValues, function (authorityValues) {
        return authorityValues.value;
    }).join(',');

    $('input#team_authority_emails').val(authorityArray);
});

$(document).on('change', 'input.member-email', function() {

    var memberValues = $(this);

    var memberArray = [].map.call(memberValues, function (memberValues) {
        return memberValues.value;
    }).join(',');

    $('input#team_member_emails').val(memberArray);
});

My thoughts are that this process isn't very DRY and could be a single separate function?

[].map.call(memberValues, function (memberValues) {
  return memberValues.value;
}).join(',');

var authorityArray = [].map.call(authorityValues, function (authorityValues) {
  return authorityValues.value;
}).join(',');

What is the best way to create a function that can create and return my array? Or are there any other improvements I can make to this?

4
  • 1
    What's the point of using the map method here? There is only one element! Why not simply this.value? Commented Nov 16, 2015 at 0:06
  • 1
    The user can add as many emails as they require. So potentially there can be an infinite amount of input fields with the following class input.member-email. The database expects the values (emails) returned in the following format: [email protected], [email protected], etc. The values are returned to a hidden field. Commented Nov 16, 2015 at 0:24
  • I see what Vohuman is saying - inside the handler function this is going to only equal the value that changed, not the full set of values. Commented Nov 16, 2015 at 1:22
  • Yep just tested this and it is only returning the value that changed not the full set as you say. How would I get the full set in the function you mentioned below? Commented Nov 16, 2015 at 1:26

2 Answers 2

1

Conceptually, you want to perform a one-way binding.

All of the values from a set of inputs are to be mapped to a specified single input.

Here is a solution:

function bindValuesToTarget(sourceSelector, targetSelector) {
    var writeValuesToTarget = function() {
       var valuesString= [].map.call($(sourceSelector), function (arrayItem) {
           return arrayItem.value;
       }).join(',');

       $(targetSelector).val(valuesString);
    }        

    $(document).on(
      'change',
      $(sourceSelector),
      writeValuesToTarget
    );

    // You might want to do this the first time, 
    // just in case it never changes
    writeValuesToTarget();
}

bindValuesToTarget('input.member-email', 'input#team_member_emails');
bindValuesToTarget('input.authority-email', 'input#team_authority_emails');
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks this is what I am after. Although 1 problem. The user can add as many emails as they require. So potentially there can be an infinite amount of input fields with the following class input.member-email. The database expects the values (emails) returned in the following format: [email protected], [email protected], etc. The above only returns a single email each time it is run, unlike my current implementation that will return every email [email protected], [email protected], etc
@ThomasTaylor - I've rewritten the answer. I think this matches what you are trying to achieve
Thank you, it was my silly mistake calling this. Also added the missing comma after the $(sourceSelector).
0
$(document).on('input', 'input.authority-email', function() {
    var valCommas = this.value.replace(/\s+/, ",");  // "a,b,c,foo,bar"
    $('#team_authority_emails').val( valCommas );
});

replaces one or more spaces with a single comma

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.