-
Notifications
You must be signed in to change notification settings - Fork 60
An instance of jQuery (phpMv-ui with semantic) is injected by default in the controllers (defined in config.php)
"di"=>[
"@exec"=>array("jquery"=>function ($controller){
return \Ubiquity\core\Framework::diSemantic($controller);
})
],
The $jquery property must be added in the javadoc of a controller to activate the code completion of your IDE on this injection:
/**
* @property JsUtils $jquery
*/
class MyController extends ControllerBase{}
The view is displayed on the jquery instance, with the renderView method. This allows the compilation of the scripts, and their passage to the view.
#[Route('_default',name:'home')]
public function index(){
$this->jquery->renderView("MyController/index.html");
}
They are then integrated via the script_foot
variable (the Twig raw
filter removes the HtmlEntities protection and makes this script executable).
MyController/index.html
{{ script_foot | raw }}
The getHref
method transforms the click on a
tags with a data-target
attribute into requests performed via ajax. The listenerOn
attribute allows all future links in the body
of the page to be transformed.
The data-target
attribute defines the target of ajax requests. It defines the zone of the page in which the response will be displayed.
public function initialize() {
parent::initialize();
$this->jquery->getHref('a[data-target]','',['listenerOn'=>'body']);
}
MyController/index.html
<h1 class="ui inverted header">{{ title }}</h1>
<a class="ui inverted button" href="{{ path('ajax') }}" data-target="#ajax-content">Lien vers ajax</a>
<div class="ui text container" id="ajax-content">
</div>
{{ script_foot|raw }}
Action requested by the ajax link in example:
#[Route('ajax',name:'ajax')]
public function ajax(){
$datas=['message'=>'This is an ajax message'];
$this->loadDefaultView($datas);
}
The associated view: MyController/ajax.html
<div class="ui icon inverted message">
<i class="ui circle info icon"></i>
{{ message }}
</div>
If the user refreshes the page, Ajax is no longer requested, and only the Ajax part of the page will be refreshed and displayed. This problem needs to be solved, so that the navigation with or without Ajax leads to the same result. The solution is to modify the display of the Ajax action: If Ajax is not requested, we call the previous action, which provided the context of the page, and we ask it to display the content of the Ajax action, returned in a string.
We add to the main view an outlet
variable which will be able to display generated by the ajax action, requested without ajax.
MyController/index.html
<h1 class="ui inverted header">{{ title }}</h1>
<a class="ui inverted button" href="{{ path('ajax') }}" data-target="#ajax-content">Lien vers ajax</a>
<div class="ui text container" id="ajax-content">
{{ outlet | raw }}
</div>
{{ script_foot|raw }}
Modification of the Ajax action :
If Ajax is not requested, the main method is called, passing it the contents of the Ajax action in the outlet
variable:
#[Route('ajax',name:'ajax')]
public function ajax(){
$datas=['message'=>'This is an ajax message'];
if(!URequest::isAjax()){
$this->getView()->setVar('outlet',$this->loadDefaultView($datas,true));
$this->index();
return ;
}
$this->loadDefaultView($datas);
}
With or without Ajax, the result of the /ajax
request is now always the same.
The postFormAction
transform the submission of the form
tags with a data-target
attribute into requests performed via ajax. The listenerOn
attribute allows all future form in the body
of the page to be transformed.
The data-target
attribute defines the target of ajax requests. It defines the zone of the page in which the response will be displayed.
These forms must also set the action attribute.
public function initialize() {
parent::initialize();
if(! URequest::isAjax()){
$this->jquery->postFormAction('form[data-target]','',['listenerOn'=>'body']);
}
}
A form sample
MyFormController/form.html
<form class="ui form" action='{{ path("main.submit") }}' method="post" id="frm" data-target="#response">
<div class="ui input">
<input name="firstname" id="firstname" type="text" placeholder="Enter your firstname">
</div>
<input class="ui button" type="submit" value="Validate">
</form>
<div id="response">Response</div>
{{ script_foot | raw }}
Loaded by an action in the controller:
#[Route(path: "/form",name: "main.form")]
public function form(){
$this->jquery->renderView('MyFormController/form.html');
}
The action for the form submiting:
#[Route(path: "form/submit",name: "main.submit")]
public function submit(){
var_dump($_POST);
}