0
\$\begingroup\$

In my web application, a user will click a button which will call a function that triggers an AJAX call. That function accepts a single argument. I would like to be able to put that function in place of the anonymous function in the jQuery event handler. I suspect that this is a scoping issue...

Here is my working code:

(function () {
 'use strict';

  var postId;

  function userAddFlagToPost (userId) {
    return $.ajax({
      type: 'POST',
      timeout: 1000 * 3;,
      url: '/someApi/postId',
      data: {
        userId: userId
      },
    }).done(onFlagSubmitDone)
      .fail(onFlagSubmitDone);
  }

  function onLoggedIn() {
    var userId = getCookie('some_user_auth') || null;

    $(SELECTORS.POST_FLAG).on('click', function() {
      postId = $(this).data('postId');
    });

    $(SELECTORS.SUBMIT_BUTTON).on('click', function() {
      userAddFlagToPost(userId);
    });
  }

  function init() {
    eventQ.register(onLoggedIn);
  }

  init();
})();

I would like to be able to do:

$(SELECTORS.SUBMIT_BUTTON).on('click', userAddFlagToPost(userId));

I'd appreciate any info or advice on how to go about refactoring this code, thanks!

\$\endgroup\$

closed as off-topic by 200_success, yuri, t3chb0t, Ludisposed, Malachi Sep 23 '18 at 20:04

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Ludisposed, Malachi
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ I fear that this is off-topic, it sounds like you are asking how to implement functionality. Please only post code that already accomplishes the task at hand. \$\endgroup\$ – Malachi Sep 23 '18 at 20:04
  • \$\begingroup\$ My code is functional and does what I want. I am just looking for help to refactor the callbacks. \$\endgroup\$ – Aaron Goldsmith Sep 24 '18 at 17:08
  • \$\begingroup\$ @malachi can you please remove this question from being on hold? \$\endgroup\$ – Aaron Goldsmith Sep 24 '18 at 22:46
  • \$\begingroup\$ The problem is the following line: "I would like to be able to put that function in place of the anonymous function in the jQuery event handler." 1) I'm not sure what you mean with that, but that's my lack of JS knowledge showing and 2) that's a feature request, not a request for review. If the code is lacking a feature you want to have anyway, it's not working yet the way you want it to work. That's why it got closed, I presume. \$\endgroup\$ – Mast Sep 27 '18 at 15:55
  • \$\begingroup\$ 1. I'm asking for advice on how to refactor my existing, working code. 2. How is it a feature request when the code already does what I want. I even specified I would appreciate "any info or advice"...Should I have just posted the code and not said anything? Or maybe this should have been a question for Stack Overflow? Last thing I want to do is abuse/misuse this site. Thx. \$\endgroup\$ – Aaron Goldsmith Sep 27 '18 at 23:24
1
\$\begingroup\$

It seems that what you want is a partially-applied function. One way this can be achieved is using Function.prototype.bind().:

$(SELECTORS.SUBMIT_BUTTON).on('click', userAddFlagToPost.bind(null, userId));

Pass null as the first argument unless the context needs to be set (e.g. to this for the same context?) and then userId as the second argument will pass that as the first argument to the function. Then note that userAddFlagToPost() would then receive the event Event eventobject argument per the `.on() method.

With this approach, the function is not invoked (as it would be with your proposed syntax) but instead the partially applied function is invoked when the click handler is applied.

See this demonstrated in the snippet below:

(function() {
  'use strict';

  var postId;
  var SELECTORS = {
    SUBMIT_BUTTON: '#submitButton',
    DISPLAY_ELEMENT: '#displayElement'
  };

  function userAddFlagToPost(userId) {
    var text = 'userId passed to userAddFlagToPost: ' + userId + ' count of arguments: ' + arguments.length;
    Array.from(arguments).forEach(function(argument, index) {
      text += '<br> typeof arg[' + index + ']: ' + (typeof argument);
    });
    $(SELECTORS.DISPLAY_ELEMENT).html(text);
  }

  function init() {
    var userId = 1337; //hard code for now
    $(SELECTORS.SUBMIT_BUTTON).on('click', userAddFlagToPost.bind(null, userId));
  }
  init();
})();
#displayElement {
  border: 1px solid #0f0;
  margin: 4px;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<button id="submitButton">Click this to see the partially function called</button>
<div id="displayElement"></div>

Note that there is a jQuery shortcut method .click() that could be used in place of .on('click'):

$(SELECTORS.SUBMIT_BUTTON).click(userAddFlagToPost.bind(null, userId));
\$\endgroup\$

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