0

I have a form like:

<form data-controller="Posts" data-method="admin_add">

And then I want to call a function based on these passed data attributes when the form is submitted.

$(document).on('submit', 'form', function(e){

    e.preventDefault(); // there is no server so nothing to submit to

    var formData = $(this).serialize();

    var controller = $(this).attr('data-controller');
    var method = $(this).attr('data-method');
    // I use .attr instead of .data because .data is funny sometimes

    var fnString = controller + '.' + method;
    var fn = window[fnString];

    if (typeof fn === "function") fn(formData);

});

This is based on what I've read here: http://www.sitepoint.com/call-javascript-function-string-without-using-eval/

And it should of called:

Posts.admin_add(formData);

But it doesn't call the function... and if I remove the if statement then I get an error that it's not a function... Any ideas?

Cameron
  • 27,963
  • 100
  • 281
  • 483
  • *"I use .attr instead of .data because .data is funny sometimes"* `attr` is the **correct** way to access `data-*` attributes. The only reason for using `data` is if you're going to **store** data on the element that shouldn't be in an attribute. – T.J. Crowder Aug 12 '14 at 13:47
  • @T.J.Crowder That isn't the question though... I just put that comment so other developers know why I used that method! – Cameron Aug 12 '14 at 13:48
  • @Cameron: I understand. I'm just saying, it's the correct way, nothing you (should) have to explain. (Sadly a lot of people misunderstand `data`...) – T.J. Crowder Aug 12 '14 at 13:49
  • Strictly speaking, the *best* way would be `this.getAttribute("data-controller")` -- no reason to waste processor time with jQuery when the [Vanilla JS](http://vanilla-js.com/) equivalent is near-identical. – Niet the Dark Absol Aug 12 '14 at 13:50
  • @NiettheDarkAbsol: Whether you use jQuery is nothing to do with JavaScript. I **do** wish people could get that straight. It's jQuery vs. DOM, not jQuery vs. vanilla/pure/whatever JS. It's JavaScript (or CoffeeScript/TypeScript/Dart) either way. Re using the DOM directly: The great thing about using the jQuery pseudo-equivalent is the set theory thing, where you get back `undefined` rather than throwing if the set is empty. Cuts out a lot of defensive `!== null`s. (Not in this case, of course.) – T.J. Crowder Aug 12 '14 at 13:51
  • @Niet the Dark Absol That Vanilla JS site is awesome! :D I was reading it for about 5 minutes then trying to figure out if it was a joke or not! – Cameron Aug 12 '14 at 13:57
  • @T.J.Crowder I can agree with you there, except that "vanilla JS" is being used to refer to the lack of frameworks like jQuery ;) Anyways, yeah, you do have to be quite defensive in Vanilla, but in my own opinion that just makes it clearer exactly what is happening. If my code expects an element, and there is no element, jQuery will fail completely silently with its empty set, whereas Vanilla will throw an exception. I consider that to be the course of least surprise. – Niet the Dark Absol Aug 12 '14 at 14:00
  • @NiettheDarkAbsol: Yeah. For me it goes both ways, depending on what I'm doing. – T.J. Crowder Aug 12 '14 at 14:16

1 Answers1

7

Remember, you are using square brackets to avoid using eval:

var fn = window[controller][method];
fn(formData);
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • Perfect! No idea that double square brackets would handle the period between the two variables. Thanks. – Cameron Aug 12 '14 at 13:47