Difference between revisions of "JSON Responses with JResponseJson"

From Joomla! Documentation

 
(12 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{version/tutor|3.x}}
 
{{version/tutor|3.x}}
 
== Overview ==
 
== Overview ==
 +
This is one of a series of [[API Guides]], which aim to help you understand how to use the Joomla APIs through providing detailed explanations and sample code which you can easily install and run.
  
Recently a new class JResponseJson was added to Joomla! 3.x which is able to simplify things with Ajax requests. With that class it is now possible to prepare responses to Ajax requests in a standardized and easy manner. You can have a look at the file here:
+
A new class, JResponseJson, was added to Joomla! 3 that is able to simplify Ajax requests. As of Joomla! 3.8, the core code was namespaced and aliases were added. (See the ''/libraries/classmap.php'' file at or near line 131.) The JResponseJson class was replaced by the JsonResponse class in the Joomla/CMS/Response namespace.
https://github.com/joomla/joomla-cms/blob/master/libraries/cms/response/json.php
 
It will mostly be used in controllers of components where you get the following advantages:
 
  
* Using the flag 'success' the JavaScript code (whether Mootools JRequest.JSON or jQuery.getJSON) can check whether the task was successful or not and react accordingly (If the request itself failes the error event of the JavaScript API can be used).
+
With that class it is now possible to prepare responses to Ajax requests in a standardized and easy manner.
* Then, the actual response data (if any) can be retrieved from 'data' in the JSON object and
 
* optionally a main response message from 'message'.
 
* Additionally, all gathered messages in the JApplication message queue are also automatically sent back in 'messages'. This can optionally be turned off.
 
  
Another advantage is that no $app->close(); is necessary anymore if the Ajax request is done with 'format=json' because the already existing API handles the rest. Just echo the response object at the end of the task.
+
Have a look at the revised file on [https://github.com/joomla/joomla-cms/blob/staging/libraries/src/Response/JsonResponse.php Github] or in your own site's files at ''/libraries/src/Response/JsonResponse.php''.
 +
 
 +
The JsonResponse class will mostly be used in controllers of components where you get the following advantages:
 +
 
 +
* Using the flag ''success'' the JavaScript code (whether Mootools JRequest.JSON or jQuery.getJSON) can check whether the task was successful or not and react accordingly. (If the request itself fails, the error event of the JavaScript API can be used.)
 +
* Then the actual response data, if any, can be retrieved from ''data'' in the JSON object, and
 +
* Optionally a main response message from ''message''.
 +
* Additionally, all gathered messages in the JApplication message queue are automatically sent back in ''messages''. This can be turned off.
 +
 
 +
Another advantage is that no ''$app->close();'' is necessary if the Ajax request is done with ''format=json''. The existing API handles the rest. Just echo the response object at the end of the task.
  
 
== How to Use ==
 
== How to Use ==
 
=== Most Common Cases ===
 
=== Most Common Cases ===
 
 
Here is an example controller file:
 
Here is an example controller file:
  
Line 29: Line 33:
 
       $result = $this->getModel('example')->createSomething($anyParam);
 
       $result = $this->getModel('example')->createSomething($anyParam);
  
       echo new JResponseJson($result);
+
       echo new JsonResponse($result);
 
     }
 
     }
 
     catch(Exception $e)
 
     catch(Exception $e)
 
     {
 
     {
       echo new JResponseJson($e);
+
       echo new JsonResponse($e);
 
     }
 
     }
 
   }
 
   }
 
}</source>
 
}</source>
  
As you can see in the default case the return value of something that has been calculated by the model is simply pushed into a new JResponseJson object and written to the output. This will automatically create a JSON encoded string as follows (except that it is more compressed in reality):
+
In the default case, the return value of something that has been calculated by the model is simply pushed into a new JsonResponse object and written to the output. This will automatically create a JSON-encoded string as follows:
  
<source>
+
<source lang="json">
 
{"success":true,"message":null,"messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
{"success":true,"message":null,"messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
</source>
 
</source>
  
So, in the 'data' field you can send any array, object or value you want and the 'success' flag is automatically set to 'true'.
+
In the ''data'' field, you can send any array, object or value you want and the ''success'' flag is automatically set to ''true''.
  
If any exception occured in the model this exception is simply passed directly to a new JResponseJson object in our example which would create the following output:
+
If any exception occurred in the model, this exception is simply passed directly to a new JsonResponse object which would create the following output:
  
<source>
+
<source lang="json">
 
{"success":false,"message":"This is the message of the exception","messages":null,"data":null}
 
{"success":false,"message":"This is the message of the exception","messages":null,"data":null}
 
</source>
 
</source>
  
Since it is an exception the 'success' flag was automatically set to 'false' and the message of the exception became the main response message.
+
Since it is an exception the ''success'' flag is automatically set to ''false'' and the message of the exception becomes the main response message.
  
 
=== Additional Options ===
 
=== Additional Options ===
 
+
If no exception is passed as the first argument of the JsonResponse constructor, you can specify an arbitrary main response message by passing a string as the second argument:
If not an exception is passed as the first argument of the JResponseJson constructor you can specify an arbitrary main response message by passing a string as the second argument:
 
 
<source lang="php">
 
<source lang="php">
echo new JResponseJson($result, JText::_('COM_COMPONENT_MY_TASK_SUCCESS'));
+
echo new JsonResponse($result, JText::_('COM_COMPONENT_MY_TASK_SUCCESS'));
 
</source>
 
</source>
which creates e.g.:
+
which creates, for example:
<source>
+
<source lang="json">
 
{"success":true,"message":"The request was successful.","messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
{"success":true,"message":"The request was successful.","messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
</source>
 
</source>
  
 
+
You can also set the error flag to ''true'' with the help of the third argument (''$error''):
 
 
You can also manually set the error flag to 'false' with the help of the third argument ($error):
 
 
<source lang="php">
 
<source lang="php">
echo new JResponseJson($result, JText::_('COM_COMPONENT_MY_TASK_ERROR'), true);
+
echo new JsonResponse($result, JText::_('COM_COMPONENT_MY_TASK_ERROR'), true);
 
</source>
 
</source>
which creates e.g.:
+
which creates, for example:
<source>
+
<source lang="json">
{"success":false,"message":"The was an error.","messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
+
{"success":false,"message":"There was an error.","messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
</source>
 
</source>
Please note that this way you can also send some data back.
+
In this way you can also send some data back.
  
 
+
Regardless of having an error response or a success response, JsonResponse sends all messages back to the client that have been gathered in the application object:
Regardless of having an error response or a success response JResponseJson sends all messages back to the client that have been gathered in the application object:
 
 
<source lang="php">
 
<source lang="php">
 
$app = JFactory::getApplication();
 
$app = JFactory::getApplication();
Line 84: Line 84:
 
$app->enqueueMessage('This part was successful');
 
$app->enqueueMessage('This part was successful');
 
// Some more code
 
// Some more code
$app->enqueueMessage('Here was a small warning');
+
$app->enqueueMessage('Here was a small warning'. 'warning');
  
echo new JResponseJson($result, 'Main response message');
+
echo new JsonResponse($result, 'Main response message');
 
</source>
 
</source>
  
This results in
+
This results in:
<source>
+
<source lang="json">
 
{"success":true,"message":"Main response message","messages":"<<all the encoded messages of $app>>","data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
{"success":true,"message":"Main response message","messages":"<<all the encoded messages of $app>>","data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}
 
</source>
 
</source>
  
You can see the big advantage of that below in the JavaScript section.
+
You can see the advantage of that below in the JavaScript section.
  
If you don't want to send the messages back (rather that they stay in the session), simply set the fourth argument ($ignoreMessages) of the contructor to 'true'.
+
If you don't want to send the messages back (rather they stay in the session), set the fourth argument (''$ignoreMessages'') of the constructor to ''true''.
  
 
=== Corresponding JavaScript Code ===
 
=== Corresponding JavaScript Code ===
 
+
Here is some sample JavaScript that can be used on the client side together with JsonResponse on the server side.
Here is some sample JavaScript used which can be used on the client side together with JResponseJson on the server side.
+
The example is written with Mootools code. Something similar can also be done with jQuery or any other JavaScript library for Ajax requests.
The example is written with some Mootools code, but something similar can also be done with jQuery or any other JavaScript library for Ajax requests.
 
  
 
<source lang="javascript">
 
<source lang="javascript">
Line 112: Line 111:
 
{
 
{
 
// Success flag is set to 'false' and main response message given
 
// Success flag is set to 'false' and main response message given
// So you can alert it or insert it into some HTML element
+
// so you can alert it or insert it into some HTML element
 
alert(r.message);
 
alert(r.message);
 
}
 
}
Line 134: Line 133:
 
{
 
{
 
// Reaching this point means that the Ajax request itself was not successful
 
// Reaching this point means that the Ajax request itself was not successful
// So JResponseJson was never called
+
// So JsonResponse was never called
 
alert('Ajax error');
 
alert('Ajax error');
 
}.bind(this),
 
}.bind(this),
Line 140: Line 139:
 
{
 
{
 
// Reaching this point means that the Ajax request was answered by the server, but
 
// Reaching this point means that the Ajax request was answered by the server, but
// the response was no valid JSON (this happens sometimes if there were PHP errors,
+
// the response was not valid JSON. (This happens sometimes if there were PHP errors,
// warnings or notices during the development process of a new Ajax request).
+
// warnings or notices during the development process of a new Ajax request.)
 
alert(error + "\n\n" + text);
 
alert(error + "\n\n" + text);
 
}.bind(this)
 
}.bind(this)
Line 147: Line 146:
 
req.post('anyparam=myvalue');
 
req.post('anyparam=myvalue');
 
</source>
 
</source>
 
  
 
== Best Practice ==
 
== Best Practice ==
As already seen above, code of the controller can be kept very simple using JResponseJson. The model is calculating the data which can be passed to JResponseJson afterwards (of course you can still modify it in the controller if you want to). If you are developing an MVC component you should save such a controller in a file called 'mycontroller.json.php' and place it inside your 'controllers' folder.
+
As seen above, controller code can be kept simple using JsonResponse. The model is calculating the data which can be passed to JsonResponse afterwards. (You can still modify it in the controller.) If you are developing an MVC component, save such a controller in a file called ''mycontroller.json.php'' and place it inside your ''controllers'' folder. That controller is automatically executed if your request URL contains ''format=json''.
This way, that controller is automatically executed if your request URL contains 'format=json'.
 
  
Please note that as you can see in the example, there is no need for closing the application (e.g. $app->close();) because the architecture of Joomla! handles that for you. So, this is very clean and good programming.
+
Note that there is no need for closing the application (''$app->close();'') because the architecture of Joomla! handles that for you.
  
 
<source lang="php">
 
<source lang="php">
Line 166: Line 163:
 
       $count = $this->getModel('example')->countSomething($anyParam);
 
       $count = $this->getModel('example')->countSomething($anyParam);
  
       echo new JResponseJson($count);
+
       echo new JsonResponse($count);
 
     }
 
     }
 
     catch(Exception $e)
 
     catch(Exception $e)
 
     {
 
     {
       echo new JResponseJson($e);
+
       echo new JsonResponse($e);
 
     }
 
     }
 
   }
 
   }
 
}</source>
 
}</source>
 
 
  
 
===Additional Note===
 
===Additional Note===
 
+
If you want to support users without JavaScript by doing the same task with a normal request and a final redirect back to the page, there is not much you have do additionally. Just create another controller (with a name such as ''mycontroller.php'') and code like this:
If you want to support no-js users by for example doing the same task with a normal request and a final redirect back to the page, there is not much you have do additionally. Just create another controller (now with name 'mycontroller.php') and code like this:
 
  
 
<source lang="php">
 
<source lang="php">
Line 204: Line 198:
 
}</source>
 
}</source>
  
No changes necessary in the model!
+
No changes are necessary in the model!
 +
 
 +
Depending on whether you do the request with ''format=json'' (Ajax-Request) or via normal request (without the ''format'' parameter), the correct controller is executed automatically and the response is prepared accordingly.
 +
 
 +
== Sample Component Code ==
 +
Below is the code for a simple Joomla component which you can install and run to demonstrate use of the JReponseJson functionality. Place the following 3 files into a folder called "com_jresponse_json_demo". Then zip up the folder to create <tt>com_jresponse_json_demo.zip</tt> and install this as a component on your Joomla instance.
 +
 
 +
<tt>com_jresponse_json_demo.xml</tt> Manifest file for the component
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="utf-8"?>
 +
<extension type="component" version="3.1.0" method="upgrade">
  
So depending on whether you do the request with 'format=json' (Ajax-Request) or via normal request (without 'format' parameter), the correct controller is executed automatically and the response is prepared accordingly.
+
<name>com_jresponse_json_demo</name>
 +
<version>1.0.0</version>
 +
<description>Demo of jresponse_json</description>
 +
 +
<administration>
 +
</administration>
  
 +
<files folder="site">
 +
<filename>jresponse_json_demo.php</filename>
 +
<filename>calc.js</filename>
 +
</files>
 +
</extension>
 +
</source>
 +
 +
<tt>jresponse_json_demo.php</tt> PHP file which displays the form and handles the Ajax request.
 +
<source lang="php">
 +
<?php
 +
defined('_JEXEC') or die('Restricted access');
 +
 +
use Joomla\CMS\Factory;
 +
 +
$app = Factory::getApplication(); 
 +
$input = $app->input;
 +
 +
$task = $input->get("task", "", "cmd");
 +
 +
function divide($a, $b) 
 +
{
 +
if ($b == 0)
 +
{
 +
throw new Exception('Division by zero!');
 +
}
 +
return $a/$b;
 +
}
 +
 +
if ($task == "divide") {  // respond to Ajax
 +
$x = $input->get("x", 0, "float");
 +
$y = $input->get("y", 0, "float");
 +
$app->enqueueMessage("Enqueued notice", "notice");
 +
$app->enqueueMessage("Enqueued warning", "warning");
 +
try
 +
{
 +
$result = divide($x, $y);
 +
echo new JResponseJson($result, "It worked!");
 +
}
 +
catch (Exception $e)
 +
{
 +
echo new JResponseJson($e);
 +
}
 +
} else {  // normal HTTP GET - display the form
 +
JHtml::_('jquery.framework');  // use JQuery for Ajax call
 +
$document = JFactory::getDocument();
 +
$document->addScript(JUri::root() . "components/com_jresponse_json_demo/calc.js");
 +
 +
echo '<label>x</label><input id="x" type="number" step="any">';
 +
echo '<label>y</label><input id="y" type="number" step="any"><br>';
 +
echo '<button onclick="calculate();">Divide!</button><br>';
 +
echo '<label>answer</label><input id="answer" type="text" readonly><br>';
 +
}
 +
</source>
 +
 +
<tt>calc.js</tt> Javascript file which initiates the Ajax request and handles the response.
 +
<source lang="javascript">
 +
function calculate() {
 +
x = document.getElementById("x").value;
 +
y = document.getElementById("y").value;
 +
jQuery.ajax({ // by default jQuery sends Ajax requests to the same URL as the current page
 +
        data: { task: "divide", format: "json", x: x, y: y },
 +
})
 +
.done(function(result, textStatus, jqXHR)
 +
{
 +
if (result.success)
 +
{
 +
jQuery("#answer").val(result.data);
 +
console.log("Message from server was " + result.message);
 +
}
 +
else
 +
{
 +
alert(result.message);
 +
}
 +
// display the enqueued messages in the message area
 +
Joomla.renderMessages(result.messages);
 +
})
 +
.fail(function(jqXHR, textStatus, errorThrown)
 +
{
 +
console.log('ajax call failed' + textStatus);
 +
});
 +
}
 +
</source>
 +
 +
Once the component is installed, navigate to your site home page and add the following parameter to the URL  <tt>?option="com_jresponse_json_demo"</tt> to navigate to this component. The component prompts for 2 values, x and y, and when you click on the Divide button it makes an Ajax call to the server. The server performs the calculation, including checking for division by zero, and then returns the answer using JReponseJson.
 +
 +
The server also includes 2 enqueued messages in the response, which the javascript displays in the message area by calling <tt>Joomla.renderMessages()</tt> (which is a javascript function found in the Joomla core.js file).
 +
 +
(The server code has been designed to focus on the JResponseJson API. If you are developing a genuine Joomla component then you should use the Joomla Form API and MVC approach as outlined in [[Basic form guide]].)
 +
 +
== Further Reading ==
 +
Another example of using JReponseJson can be found in [[J3.x:Developing_an_MVC_Component/Adding_AJAX]].
 +
 +
Ajax can also be used in Joomla Modules and Plugins, as described in [[Using Joomla Ajax Interface]].
 +
 +
[[Category:AJAX]]
 +
[[Category:Component Development]]
 
[[Category:Extension development]]
 
[[Category:Extension development]]
[[Category:Component Development]]
 
[[Category:AJAX]]
 

Latest revision as of 16:09, 24 June 2022

Overview[edit]

This is one of a series of API Guides, which aim to help you understand how to use the Joomla APIs through providing detailed explanations and sample code which you can easily install and run.

A new class, JResponseJson, was added to Joomla! 3 that is able to simplify Ajax requests. As of Joomla! 3.8, the core code was namespaced and aliases were added. (See the /libraries/classmap.php file at or near line 131.) The JResponseJson class was replaced by the JsonResponse class in the Joomla/CMS/Response namespace.

With that class it is now possible to prepare responses to Ajax requests in a standardized and easy manner.

Have a look at the revised file on Github or in your own site's files at /libraries/src/Response/JsonResponse.php.

The JsonResponse class will mostly be used in controllers of components where you get the following advantages:

  • Using the flag success the JavaScript code (whether Mootools JRequest.JSON or jQuery.getJSON) can check whether the task was successful or not and react accordingly. (If the request itself fails, the error event of the JavaScript API can be used.)
  • Then the actual response data, if any, can be retrieved from data in the JSON object, and
  • Optionally a main response message from message.
  • Additionally, all gathered messages in the JApplication message queue are automatically sent back in messages. This can be turned off.

Another advantage is that no $app->close(); is necessary if the Ajax request is done with format=json. The existing API handles the rest. Just echo the response object at the end of the task.

How to Use[edit]

Most Common Cases[edit]

Here is an example controller file:

class MyController extends JControllerLegacy
{
  public function execute()
  {
    try
    {
      $anyParam = JFactory::getApplication()->input->get('anyparam');

      $result = $this->getModel('example')->createSomething($anyParam);

      echo new JsonResponse($result);
    }
    catch(Exception $e)
    {
      echo new JsonResponse($e);
    }
  }
}

In the default case, the return value of something that has been calculated by the model is simply pushed into a new JsonResponse object and written to the output. This will automatically create a JSON-encoded string as follows:

{"success":true,"message":null,"messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}

In the data field, you can send any array, object or value you want and the success flag is automatically set to true.

If any exception occurred in the model, this exception is simply passed directly to a new JsonResponse object which would create the following output:

{"success":false,"message":"This is the message of the exception","messages":null,"data":null}

Since it is an exception the success flag is automatically set to false and the message of the exception becomes the main response message.

Additional Options[edit]

If no exception is passed as the first argument of the JsonResponse constructor, you can specify an arbitrary main response message by passing a string as the second argument:

echo new JsonResponse($result, JText::_('COM_COMPONENT_MY_TASK_SUCCESS'));

which creates, for example:

{"success":true,"message":"The request was successful.","messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}

You can also set the error flag to true with the help of the third argument ($error):

echo new JsonResponse($result, JText::_('COM_COMPONENT_MY_TASK_ERROR'), true);

which creates, for example:

{"success":false,"message":"There was an error.","messages":null,"data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}

In this way you can also send some data back.

Regardless of having an error response or a success response, JsonResponse sends all messages back to the client that have been gathered in the application object:

$app = JFactory::getApplication();
// Some code ($result = ...)
$app->enqueueMessage('This part was successful');
// Some more code
$app->enqueueMessage('Here was a small warning'. 'warning');

echo new JsonResponse($result, 'Main response message');

This results in:

{"success":true,"message":"Main response message","messages":"<<all the encoded messages of $app>>","data":{"myfirstcustomparam":1,"mysecondcustomparam":42, ...}}

You can see the advantage of that below in the JavaScript section.

If you don't want to send the messages back (rather they stay in the session), set the fourth argument ($ignoreMessages) of the constructor to true.

Corresponding JavaScript Code[edit]

Here is some sample JavaScript that can be used on the client side together with JsonResponse on the server side. The example is written with Mootools code. Something similar can also be done with jQuery or any other JavaScript library for Ajax requests.

var req = new Request.JSON({
	method: 'post',
	url: 'index.php?option=com_component&task=mycontroller.execute&format=json',
	onSuccess: function(r)
	{
		if (!r.success && r.message)
		{
			// Success flag is set to 'false' and main response message given
			// so you can alert it or insert it into some HTML element
			alert(r.message);
		}

		if (r.messages)
		{
			// All the enqueued messages of the $app object can simple be
			// rendered by the respective helper function of Joomla!
			// They will automatically be displayed at the messages section of the template
			Joomla.renderMessages(r.messages);
		}

		if (r.data)
		{
			// Here you can access all the data of your response
			alert(r.data.myfirstcustomparam);
			alert(r.data.mysecondcustomparam);
		}
	}.bind(this),
	onFailure: function(xhr)
	{
		// Reaching this point means that the Ajax request itself was not successful
		// So JsonResponse was never called
		alert('Ajax error');
	}.bind(this),
	onError: function(text, error)
	{
		// Reaching this point means that the Ajax request was answered by the server, but
		// the response was not valid JSON. (This happens sometimes if there were PHP errors,
		// warnings or notices during the development process of a new Ajax request.)
		alert(error + "\n\n" + text);
	}.bind(this)
});
req.post('anyparam=myvalue');

Best Practice[edit]

As seen above, controller code can be kept simple using JsonResponse. The model is calculating the data which can be passed to JsonResponse afterwards. (You can still modify it in the controller.) If you are developing an MVC component, save such a controller in a file called mycontroller.json.php and place it inside your controllers folder. That controller is automatically executed if your request URL contains format=json.

Note that there is no need for closing the application ($app->close();) because the architecture of Joomla! handles that for you.

class MyController extends JControllerLegacy
{
  public function execute()
  {
    try
    {
      $anyParam = JFactory::getApplication()->input->get('anyparam');

      $count = $this->getModel('example')->countSomething($anyParam);

      echo new JsonResponse($count);
    }
    catch(Exception $e)
    {
      echo new JsonResponse($e);
    }
  }
}

Additional Note[edit]

If you want to support users without JavaScript by doing the same task with a normal request and a final redirect back to the page, there is not much you have do additionally. Just create another controller (with a name such as mycontroller.php) and code like this:

class MyController extends JControllerLegacy
{
  public function execute()
  {
    $app = JFactory::getApplication();
    $app->setRedirect(JRoute::_('index.php?option=com_mycomponent&view=myview', false));

    try
    {
      $anyParam = JFactory::getApplication()->input->get('anyparam');

      $count = $this->getModel('example')->countSomething($anyParam);

      $app->setMessage(JText::plural('COM_COMPONENT_COUNT_TASK', $count));
    }
    catch(Exception $e)
    {
      $app->setMessage(JText::sprintf('COM_COMPONENT_COUNT_TASK_ERROR', $e->getMessage()), 'error');
    }
  }
}

No changes are necessary in the model!

Depending on whether you do the request with format=json (Ajax-Request) or via normal request (without the format parameter), the correct controller is executed automatically and the response is prepared accordingly.

Sample Component Code[edit]

Below is the code for a simple Joomla component which you can install and run to demonstrate use of the JReponseJson functionality. Place the following 3 files into a folder called "com_jresponse_json_demo". Then zip up the folder to create com_jresponse_json_demo.zip and install this as a component on your Joomla instance.

com_jresponse_json_demo.xml Manifest file for the component

<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1.0" method="upgrade">

	<name>com_jresponse_json_demo</name>
	<version>1.0.0</version>
	<description>Demo of jresponse_json</description>
	
	<administration>
	</administration>

	<files folder="site">
		<filename>jresponse_json_demo.php</filename>
		<filename>calc.js</filename>
	</files>
</extension>

jresponse_json_demo.php PHP file which displays the form and handles the Ajax request.

<?php
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Factory;

$app = Factory::getApplication();  
$input = $app->input;

$task = $input->get("task", "", "cmd");

function divide($a, $b)  
{
	if ($b == 0)
	{
		throw new Exception('Division by zero!');
	}
	return $a/$b;
}

if ($task == "divide") {   // respond to Ajax
	$x = $input->get("x", 0, "float");
	$y = $input->get("y", 0, "float");
	$app->enqueueMessage("Enqueued notice", "notice");
	$app->enqueueMessage("Enqueued warning", "warning");
	try 
	{
		$result = divide($x, $y);
		echo new JResponseJson($result, "It worked!");
	}
	catch (Exception $e)
	{
		echo new JResponseJson($e);
	}
} else {   // normal HTTP GET - display the form
	JHtml::_('jquery.framework');  // use JQuery for Ajax call
	$document = JFactory::getDocument();
	$document->addScript(JUri::root() . "components/com_jresponse_json_demo/calc.js");

	echo '<label>x</label><input id="x" type="number" step="any">';
	echo '<label>y</label><input id="y" type="number" step="any"><br>';
	echo '<button onclick="calculate();">Divide!</button><br>';
	echo '<label>answer</label><input id="answer" type="text" readonly><br>';
}

calc.js Javascript file which initiates the Ajax request and handles the response.

function calculate() {
	x = document.getElementById("x").value;
	y = document.getElementById("y").value;
	jQuery.ajax({	// by default jQuery sends Ajax requests to the same URL as the current page
        	data: { task: "divide", format: "json", x: x, y: y },
		})
		.done(function(result, textStatus, jqXHR)
		{
			if (result.success)
			{
				jQuery("#answer").val(result.data); 
				console.log("Message from server was " + result.message);
			}
			else
			{
				alert(result.message);
			}
			// display the enqueued messages in the message area
			Joomla.renderMessages(result.messages);
		})
		.fail(function(jqXHR, textStatus, errorThrown)
		{
			console.log('ajax call failed' + textStatus);
		});
}

Once the component is installed, navigate to your site home page and add the following parameter to the URL ?option="com_jresponse_json_demo" to navigate to this component. The component prompts for 2 values, x and y, and when you click on the Divide button it makes an Ajax call to the server. The server performs the calculation, including checking for division by zero, and then returns the answer using JReponseJson.

The server also includes 2 enqueued messages in the response, which the javascript displays in the message area by calling Joomla.renderMessages() (which is a javascript function found in the Joomla core.js file).

(The server code has been designed to focus on the JResponseJson API. If you are developing a genuine Joomla component then you should use the Joomla Form API and MVC approach as outlined in Basic form guide.)

Further Reading[edit]

Another example of using JReponseJson can be found in J3.x:Developing_an_MVC_Component/Adding_AJAX.

Ajax can also be used in Joomla Modules and Plugins, as described in Using Joomla Ajax Interface.