1

I'm trying to find a better way to write a piece of jQuery but I couldn't figure it out on my own.

$('.ajaxButton').click(function(event) {

    event.preventDefault();

    var button = $(this).data('button');
    var action = $(this).data('buttonaction');
    var target = $(this).data('buttontarget');

    // The following code needs a rewrite
    if (action === 'fadeIn') {
        $(target).fadeIn();
    } else if (action === 'slideDown') {
        $(target).slideDown();      
    } else if (action === 'fadeToggle') {
        $(target).fadeToggle();     
    } else if (action === 'slideToggle') {
        $(target).slideToggle();        
    } else {
        console.log('Action not found for ' + button + ' button.');
    }


});

In order to avoid having to write the same code over and over again, I wrote the above JS for buttons I create in my web application. The above code works with the following anchor:

<a href="#" 
    class="button ajaxButton" 
    data-button="showForm"
    data-buttonaction="slideToggle"
    data-buttontarget=".showForm" >...</a>

What I have been trying to figure out is if there is a better way to write the following piece of code:

if (action === 'fadeIn') {
    $(target).fadeIn();
} else if (action === 'slideDown') {
    $(target).slideDown();      
} else if (action === 'fadeToggle') {
    $(target).fadeToggle();     
} else if (action === 'slideToggle') {
    $(target).slideToggle();        
} else {
    console.log('Action not found for ' + button + ' button.');
}

I would like to avoid the use of if: else statements. My first instinct was to have some sort of array that contains all possible actions. From there, I conduct a simple if action is in array do....

var actionArray = new Array('fadeIn', 'slideDown'...);

if ($.inArray(action, actionArray)) {
    $(target).action();
}

But I have no idea how to create the function. Can I call functions based on array values? Or can I convert strings to functions? I think the closest I could find was to use the eval() function.

Is there a better way to do this? Or will I have to use if else statements?

3
  • Possible duplicate of jQuery call function from a string Commented May 7, 2019 at 12:37
  • 1
    if ( target[ action ] ) target[ action ](); could work. But no idea how to convert it to jquery. The point is, as long as the action is the same spelling as the method name you are calling, you can use the action string to call the function in bracket notation instead of dot notation. Never use eval() unless you can exactly explain why you are using it. You could also use a switch() statement same way as inside reducers. PS: if you use an actual button instead of a hyperlink you do not have to preventDefault(). Commented May 7, 2019 at 12:37
  • 2
    @Shilly, it is simply $(target)[action]() Commented May 7, 2019 at 12:43

3 Answers 3

1

You can target a property within an object using bracket notation (obj['prop']) instead of dot notation (obj.prop). So you can do something like this:

const validActions = ['fadeIn', 'slideDown'];

function doSomethingWithTarget(target, something) {
  if (validActions.includes(something)) {
    target[something]();
  }
}

doSomethingWithTarget($('#element'), 'slideDown'); // $('#element').slideDown();

More info: Working with objects @MDN, Property accessors @MDN

Sign up to request clarification or add additional context in comments.

2 Comments

Hi, Thank you this worked well for me. However, I wasn't able to find anything on the jQuery API website regarding the Bracket Notations or why I do not need the . to call the functions. I would love to learn a little more about this.
@UzairHayat It doesn't necessarily have anything to do with jQuery, but rather with JS objects in general. A jQuery object is just a JS object with a bunch of methods/properties defined in it (like fadeIn, slideDown etc.). I've added links to MDN pages with extra info to the answer.
0

Here's my attempt :

$('.ajaxButton').click(event => {
  event.preventDefault();

  let $this = $(this),
    button = $this.data('button'),
    action = $this.data('buttonaction'),
    $target = $($this.data('buttontarget'));

  try {
    $target[action]();
  } catch (error) {
    console.log('Action not found for ' + button + ' button.');
  }
});

target.fadeIn can also be written target["fadeIn"]. If it is a function, you can then call it the same way : target.fadeIn() or target["fadeIn"](). Then the argument can be dynamic (variable) : target[action]()

Comments

0

What you can do is check of the function excist for the target, and if so execute it.

$('.ajaxButton').click(function(event) {

  event.preventDefault();

  var button = $(this).data('button');
  var action = $(this).data('buttonaction');
  var target = $(this).data('buttontarget');

  //check if the function excist for target object
  if (typeof $(target)[action] === 'function') {
    //if so execute it.
    $(target)[action]();
  } else {
    console.log('function: ' + action + ' not found for target: ' + target);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#" class="button ajaxButton" data-button="showForm" data-buttonaction="slideToggle" data-buttontarget=".showForm">testbutton</a>

<div class="showForm">test toggle div</div>

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.