1

I've set up an Ajax call in my component.

I seem to have got the initial call, the controller, the data model is working because when I make the JavaScript call I'm showing this in the code inspector as the response:

({"userblock":"none","fileName":"","fileLocat":"","username":null,"type":"current"});

But I can't seem to access the data via my JavaScript:

function initialise() {

    console.log(" start Ajax Call ");
    jQuery.ajax({
        type: "POST",
        url: 'index.php?option=com_daily&task=ajax.initialisePerson&format=json',

        data: registration,
        success: function(response){
            console.log("back from ajax");// this shows nothing
            console.log("response is "+response[0].userblock);// this shows nothing
            if(response.message !=""){....

I guess I'm doing something stupid but any help would be great.

The controller code is:

public function ajax()
{
    $user       = JFactory::getUser();
    $jinput     = JFactory::getApplication()->input;
    // Check Token!
    $token      = JSession::getFormToken();
    $call_token = $jinput->get('token', 0, 'ALNUM');
    if($token == $call_token)
    {
        $task = $this->getTask();
        switch($task)
        {
            case 'initialisePerson':
                try
                {
                    $returnRaw = $jinput->get('raw', false, 'BOOLEAN');
                    $viewValue = $jinput->get('view', NULL, 'INT');

                    if($viewValue)
                    {
                        $result = $this->getModel('ajax')->displayDetails($viewValue);
                    }
                    else
                    {
                        $result = false;
                    }
                    if($callback = $jinput->get('callback', null, 'CMD'))
                    {
                        echo $callback . "(".json_encode($result).");";
                    }
                    elseif($returnRaw)
                    {
                        echo json_encode($result);
                    }
                    else
                    {
                        echo "(".json_encode($result).");";
                    }
                }
                catch(Exception $e)
                {
                    if($callback = $jinput->get('callback', null, 'CMD'))
                    {
                        echo $callback."(".json_encode($e).");";
                    }
                    else
                    {
                        echo "(".json_encode($e).");";
                    }
                }
                break;
        }
    }

So doing this led me to the problem:

echo "(".json_encode($e).");";

I used this code and it should be

echo json_encode($result);

All works now.

1

How did you come up with the round brackets? The semicolon ist also wrong.

Objects come with curly brackets and arrays with square brackets. Your string will work with the 2 issues corrected. The values can be accessed with response.userblock, response.fileName ... There is no "message" in the response, so you won't get anything there.

You should use the json_encode function in PHP. It might also be a good idea to catch the errors.

  • Thanks for the comments. I tracked down the problem and the code was inserting brackets! Thanks for taking the time to suggest where to look – user1616338 Sep 25 '18 at 8:32
1

Regarding your ajax call to the json generating contoller, method is the more modern term rather than type since JQuery 1.9

jQuery.ajax({
    method: 'POST',  // method is more modern than type
    url: 'index.php?option=com_daily&task=ajax.initialisePerson&format=json',
    data: registration,
    success: (function (response) { ...

I haven't personally built an ajax-powered component yet, but there is a dedicated tutorial for this that shows a more readable syntax for passing the parameters of the ajax call.

https://docs.joomla.org/J3.x:Developing_an_MVC_Component/Adding_AJAX



As for you controller, be very careful to only pass valid json on every possible response.

You are correct in identifying that wrapping your json string in ( and ); will break the string syntax, but you need to check your other response strings as well. With echo $callback . "(".json_encode($result).");";, $callback will break your json string too.

My recommendation is to perform all of your conditional handling and save all of your data into a $response variable. (I always push data into my $response array as associated elements like:

if ($condition === true) {
    $response['message'] = "pass";                   // whatever
    $response['data'] = [1,2,3];                     // whatever
} else {
    $response['message'] = "fail";                   // whatever
    $response['error'] = "Syntax Error in X Query";  // whatever
}

Then I pass it back via a tidy little script-ending Joomla feature:

echo new JResponseJson($response);

This way, your php data is always perfectly encoded and the encoding call is only performed once at the end.

Now, when the data is passed back to jQuery as a response string, use response = JSON.parse(response); to convert the string into something that javascript can chew on. If my response data can include optional elements, I check if it exists before I try to access it by writing an in condition (to prevent generating warnings).

Here's a taste of that:

success(function (response) {
    //console.log(JSON.stringify(response));  // see what Joomla generates for you
    response = JSON.parse(response);

    if ("message" in response.data) {
        if (response.data.message == "pass") {
            if ("data" in response.data) {
                console.log(response.data.data);
            } else {
                console.log("uhoh, 'data' element not found in response.data");
            }
        } elseif (response.data.message == "fail") {
            if ("error" in response.data) {
                console.log(response.data.error);
            } else {
                console.log("uhoh, 'error' element not found in response.data");
            }
        } else {
            console.log("Unknown response.data.message value");
        }
    } else {
        console.log("uhoh, 'message' element not found in response.data");
    }
}

Sometimes I use message as a key for a value that I want to display in a bootstrap box. Sometimes I use alert as a key for a value that I want to display as a javascript popup/alert. Never offer raw mysql error codes or messages in the response, if you are going to pass back an error element, make it specific enough to guide you and your users, but general enough that malicious parties can't derive useful details from it. When you isolate separate values in this way, it can make manipulating the data in your javascript cleaner and more intuitive for other programmers.

  • Thanks for this. It was interesting to read Joomla's tutorial. I actually think it's simpler to pass an object and use the object in the php controller/model rather than the way they do it. That said I got it working so I'm happy :) thanks for the suggestions – user1616338 Sep 25 '18 at 8:31

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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