-2

I'm working on a song site, where you can rate songs, singers etc, and you also have the option to add them to your favourites.

After a while I've noticed when I add/remove song/singer from my favourites, I pretty much repeate the same ajax request multiple times, only with a different feedback message, so I decided to create a separate function of that request, and in other methods I just call this.

For this I set things such as the route of the button, feedback, message etc in the parameter of the favourite function, as you can see below.

The feedback() function is not really important I believe, I just shared if someone would like to know how it looks like, or if they'd actually find it important anyway.

function feedback($feedback_route,$message_route,$alert_class,$message){
    $($feedback_route).removeClass("d-none");
    $($feedback_route).addClass($alert_class);
    $($feedback_route).addClass("animated fadeIn");
    $($message_route).html($message);
    setTimeout(() => {
        $($feedback_route).addClass("animated fadeOut");
    }, 2000);
    setTimeout(() => {
        $($feedback_route).addClass("d-none");
        $($feedback_route).removeClass($alert_class);
        $($message_route).html("");
    }, 2500);
}

function favourite($ajax_route,$post,$button_route,$event,$feedback_route,
        $message_route,$success_message,$error_message){
        $.ajax({
            url: $ajax_route,
            type: "post",
            data: {
                $post: $($button_route).attr("value"),
                event:$event
            },
            success: (data) => {
                 feedback($feedback_route,$message_route,"alert-success",$success_message);
                setTimeout(() => {
                    $($button_route).replaceWith(data);
                }, 2500);
            },
            error: () => {
                feedback($feedback_route,$message_route,"alert-danger",$error_message);
            }
        });
    }

//-------------------------------ADD SONG TO FAVOURITES-----------------------------
$("#song-info-container #song-container").on("click","#add-to-favourites", () => {
    favourite(
        "ajax/song-favourite.php",
        "songID","#song-info-container #song-container #add-to-favourites",
        "add","#song-info-container #song-container .feedback",
        "#song-info-container #song-container #message",
        "Added!","Failed to add!"
        );
    $("#song-info-container #song-container .feedback").removeClass("animated fadeOut");
});

Here's how the original ajax request looks like:

$("#song-info-container #song-container").on("click","#add-to-favourites", () => {
    $.ajax({
        url: "ajax/song-favourite.php",
        type: "post",
        data: {
            songID: $("#song-info-container #song-container #add-to-favourites").attr("value"),
            event:"add"
        },
        success: (data) => {
            feedback("#song-info-container #song-container .feedback",
                "#song-info-container #song-container #message","alert-success","Added!");
            setTimeout(() => {
                $("#song-info-container #song-container #add-to-favourites").replaceWith(data);
            }, 2500);
        },
        error: () => {
            feedback("#song-info-container #song-container .feedback",
                "#song-info-container #song-container #message","alert-danger","Failed to add!");
        }
    });
    $("#song-info-container #song-container .feedback").removeClass("animated fadeOut");
});

And now the actual problem: first I thought it actually works, because the feedback appears with the correct message, but after it disappears(see in the setTimeOut function), the following message appears:

Notice: Undefined index: songID in G:\x\htdocs\AniSong\ajax\song-favourite.php on line 9

So the data which is also set in the parameter of the favourite function is not being passed to the other file.

Does someone know why this happens?

Or can I not do an ajax request like this in the first place?

PS: Sorry if the title doesn't make sense, didn't really know how it should be asked.

K. P.
  • 540
  • 5
  • 17
  • I don't see how this answers my question. It doesn't help at all. – K. P. Oct 18 '19 at 11:10
  • Just a note, you seem to be mixing on how a variable from `php` looks like in your `js` variables. Regardless, it would be really nice if you could also highlight where exactly is **on line 9** – Carl Binalla Oct 18 '19 at 11:18
  • The main difference I'm seeing between the "original" version and the "non-working" version is that the original version has a parameter called `songID`, and the new version has a parameter called `$post`. If you're not sending a parameter called `songID`, and your server-side code is looking for a parameter called `songID`, then doesn't that immediately explain the error? – David Oct 18 '19 at 11:18
  • @David But I set the name of that parameter when I call the method. `favourite(...,"songID",...)` The way I name these parameters doesn't matter at all as far as I know. But I just changed it just in case that'd matter, but it changed nothing. – K. P. Oct 18 '19 at 11:22
  • Possible duplicate of [How to use a variable for a key in a JavaScript object literal?](https://stackoverflow.com/questions/2274242/how-to-use-a-variable-for-a-key-in-a-javascript-object-literal) – 04FS Oct 18 '19 at 11:41
  • I already got an answer, why are you still marking it as a duplicate? That question also has nothing to do with mine. – K. P. Oct 18 '19 at 11:43

1 Answers1

1

This doesn't do what you're expecting:

{
    $post: $($button_route).attr("value"),
    event: $event
}

This won't replace $post with the string value you're passing to the function. This gives the property the literal name $post. Check the network tab of your browser's debugging tools to see what you're actually sending to the server. There is no songID property.

A quick test to validate:

let $foo = 'test';
console.log({$foo: 'baz'});

If you want to dynamically send this information, you'll need to modify your data structure to do that. Similar to how you have a dynamic "event", you'll now need a dynamic "post". Something like:

{
    post: $post,
    value: $($button_route).attr("value"),
    event: $event
}

Then in your server-side code you'd change your logic to examine the post parameter to see what field you're updating, or whatever such logic you're using server-side.


Alternatively, it just occurs to me that you could potentially create a dynamic property name. Consider something like this:

let $post = 'songID';
let data = {
    event: 'add'
};
data[$post] = 'test value';
console.log(data);

It's up to you which you think is more complex vs. which is easier for you to support.

David
  • 208,112
  • 36
  • 198
  • 279