When you call $this->set
it sets the view variables on the Controller class. These variables are eventually passed to the View Builder, which creates a new View class and returns a Result containing the HTML for this new View.
When you want to render your own View manually you need to pass it the view variables manually too - $this->set
isn't setting view variables in this new View class you created here:
$view = new View();
$content = $view->render('Home/Ajax/test_data'); // Has nothing to do with $this->set, you'd have to pass the variables in manually
This isn't generally the simplest approach to take to render an AJAX view.
While you can generally continue to use $this->set
in beforeFilter as you already are:
public function beforeFilter(Event $event)
{
$this->set('company', 'Test Company');
$this->set('address', '14 Test Street, Test, TE5 3ST');
$this->set('email', 'test@test.com');
}
.. the easiest method to make an AJAX-compatible is to enable the JSON/XML handler let the built-in JSON/XML renderers do their magic.
In the action function (index/view/edit/whatever) just include the company/address/email in the _serialize
variable.
For example, a "view" function might look like:
public function view($id = null)
{
// Do regular view stuff:
$entity = $this->MyTable->get($id);
$this->set('entity', $entity);
// Include ALL the variables you want in the response in _serialize:
$this->set('_serialize', ['entity', 'company','address', 'email']);
}
If you are sure you need a custom template (which isn't required), don't render it manually, just set the template when AJAX is detected:
if($this->request->is('ajax')){
$this->viewBuilder()->setTemplate('Home/Ajax/test_data');
}
This will automatically be rendered for you, using the variables you set with $this->set
.
If you want to make a global custom template (for example, wrapping all your data with a "response" node), for all AJAX requests, use a new Layout instead of a custom template:
if($this->request->is('ajax')){
$this->viewBuilder()->setLayout('custom_json');
}
Create this layout in src/Template/Layout/custom_json.ctp and format it as you wish, for example:
<?php
/**
* @var \App\View\AppView $this
*/
?>
{"response": <?= $this->fetch('content') ?> }
See from docs: