How can I use ajax in Zend Framework 2? - php

I am trying a small ajax application whereby I only want to return a hello world string from my controller action.
it is returning the Hello world but along with this, it is also returning my template file..
I tried to disable it the templating using the following code in the action of my controlelr
$this->_helper->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender( true );
but this returns me this error
SCREAM: Error suppression ignored for
( ! ) Notice: Undefined property: Survey\Controller\SurveyController::$_helper in C:\wamp\www\zend\module\Survey\src\Survey\Controller\SurveyController.php on line 55
SCREAM: Error suppression ignored for
( ! ) Fatal error: Call to a member function layout() on a non-object in C:\wamp\www\zend\module\Survey\src\Survey\Controller\SurveyController.php on line 55
Call Stack
How do I fix this ?
EDIT
I modifed the controller such that it looks like this
public function registerAction()
{
$result = new JsonModel(array(
'some_parameter' => 'some value',
'success'=>true,
));
return( $result );
}
Added strategies in the module..module.config in module appl directory
'strategies' => array(
'ViewJsonStrategy',
),
Still, in the ajax response I get the template being returned

Here's a solid example:
http://akrabat.com/zend-framework-2/returning-json-from-a-zf2-controller-action/
You should be using JsonMoodels to send back a Json Response.

i use this in my controller:
$view = new ViewModel(array('form'=>$my_form));
//disable layout if request by ajax
$view->setTerminal($request->isXmlHttpRequest());
$view->setTemplate('path/to/phtml');
return $view;

The user wanted to know how to get just the html back, not json as Andrews reply offers.
I also wanted the html returned so i could use it with jquery qtip plugin and this is how i did it.
I also had to make the page degrade gracefully in case javascript failed, e.g. the page output should render properly in the layout template.
/**
* Tourist Summary action
*
* #return ViewModel
*/
public function touristSummaryAction()
{
// Get the Id
$id = $this->params()->fromRoute('id', '');
// Get the data from somewhere
$data = array() ;
// Get the html from the phtml
$view = new ViewModel(
array(
'id' => $id ,
'data' => $data ,
)
);
//disable layout if request by ajax
$view->setTerminal($this->getRequest()->isXmlHttpRequest());
return $view;
}

The most simple way to send ajax requests and handle responses is the zf2 module WasabiLib https://github.com/WasabiLib/wasabilib_zf2_skeleton_application
You only need to add "ajax_element" to the class-attribute to the element which you want to cause the ajax request. It does not matter if it is a form submit or a link or a button. Visit the examples page http://www.wasabilib.org/application/pages/examples
If your application does a lot of ajax I recommend this module.

Take a look at this module. www.wasabilib.org
Seems that you it manages ajax very well.
If you do not have a application you can use the Wasabilib Skeleton https://github.com/WasabiLib/wasabilib_zf2_skeleton_application. It comes with all necessary assets in the right place.
If you already have an application you should clone the module: https://github.com/WasabiLib/wasabilib
Minimal requirements: jQuery, ZF2
Add the module to application.config.php.
Include the wasabilib.min.js after jquery in the head of your layout.phtml
How it works
in your .phtml-file you have a form like this:
<form id="simpleForm" class="ajax_element" action="simpleFormExample" method="POST">
<input type="text" name="written_text">
<input type="submit" value="try it">
</form>
Anywhere else in your phtml you can place an element where the response is shown.
In your Controller the following method:
public function simpleFormExampleAction(){
$postArray = $this->getRequest()->getPost();
$input = $postArray['written_text'];
$response = new Response(new InnerHtml("#element_simple_form","Server Response: ".$input));
return $this->getResponse()->setContent($response);
}
The form has a class "ajax_element" this will say the the library that the request will be done with an xmlhttp-request. It wont work if you do not give an id to the requesting element. So the form has the ID "simpleForm". The action is the "path/to/controller" just like a normal request.
In the controller action a new WasabiLib\Ajax\Response object is instanciated.
The InnerHtml class is for replace, prepend and append html or normal text to a selector.
In this case the selector is an ID "element_simple_form". The first parameter of the InnerHtml class is the selector. Make sure that you write #yourElementId or .yourClassSelector. For IDs an "#" and for class selectors "."
The second parameter is the Text you want to fill in this element.
The response object can handle a lot more responses which you can add with
$response->add($anotherResponseType);
A list of possible response types is here: http://www.wasabilib.org/application/pages/components
The module is build to handle ajax request an responses in a very simple way. Once you have understood the behavior you can handle almost every practical ajax need.

This works for me:
public function ajaxAction(){
$data = array(
'var1' => 'var1Value',
'var2' => 'var2Value',
);
$response = $this->getResponse();
$response->setStatusCode(200);
$response->setContent(json_encode($data));
$headers = $response->getHeaders();
$headers->addHeaderLine('Content-Type', 'application/json');
return $response;
}
Output:
{"var1":"var1Value","var2":"var2Value"}

Related

How did you bind datas to a view in Codeigniter ( likes View Composers in laravel)?

If you have data that you want to be bound to a view each time that view is
rendered,a view composer can help you ...
This task can be easily archived in laravel, but I am now using Codeigniter, there is no view composers things. What I have done now is, I create a custom view method, just like below
public function view($page,$params=null,$return=false)
{
// Every time I invoke this method, $nav will be passed to 'navigation' view.
$nav=[
'user' =>'Adam'
];
//return the views as view_partials instead of displayed
$view_partials = array(
'navigation' => $this->obj->load->view('partials/nav',$nav,true),
'page_content' => $this->obj->load->view($page,$params,true)
);
// load layout with the view_partials which contain bound data.
$this->obj->load->view($this->_layout,$view_partials,$return);
}
This method returns views as 'string', it can not works with json or complex page.... Thank you.
Ok, lets make this simple
$this->load->view(path_to_htmlpage, $bound_data, FALSE);
or
$this->load->view(path_to_htmlpage, $bound_data); // by default 3rd param is FALSE
this will render html page
If you want to get html page as a string, set 3rd parameter to TRUE
$html_string = $this->load->view(path_to_htmlpage, $bound_data, TRUE);
check https://ellislab.com/codeigniter/user-guide/general/views.html
public function view($page,$params=null,$return=false)
{
$nav['user']='adam';
$data['navigation']= $this->load->view("partials/nav",$nav,true);
$data['page_content'] = $this->load->view($page,$params,true)
$this->load->view('your_page',$data);
}
in yor view page ie.your_page you can use variables $navigation and $page_content to display the pages

Zend Framework 1 pass parameters using get to the route

I hope the title does not sound too confusing, but I had no idea how to name my problem.
Brief intro:
I'm using Zend 1.1X.
At the moment I've been working with a search form sending few parameters via POST.
Now I have to change it to use GET, I have a route created looking similar to that:
"search/what/:what/shape/:shape"
and so on, I also have 2 optional parameters which takes null as default.
I'm trying to generate an URL (using Zend View Helper Url) at form's action, but it throws an exception:
Uncaught exception 'Zend_Controller_Router_Exception' with message what is not specified
I Now don't have idea what should I do. If I change my route to "search" only, it then sends the form correctly, but I end up with "search?what=XXXX&shape=YYYY" instead of "search/what/XXXX/shape/YYYY".
Is there any way that could be handled the way I like??? :>
#EDIT
I think this should also be mentioned - I have a different form, similar one, pointing to a route without parameters specified as well and the uri gets "translated" to the form of "key/value" pairs. The only difference between them is that the first one does not use Url helper, instead has the method part hard-coded and my form is being submitted programatically (button => jQuery stuff => submit). Would that make a difference here, as I believe it should not? :>
I hope any possible source of this behaviour will come up to you, because I'm really stuck at the moment and I simply can't find what's wrong..
Thanks in advance!
With the GET method a form generates an url like this: action?param1=val1&param2=val2&....
I see two solutions:
The first is to regenerate the URL by javacsript, we can imagine something like this:
<form method="get" id="id_form">
....
</form>
<script>
var objet_form = document.getElementById('id_form');
function gestionclic(event){
var url = objet_form.action;
for(var i = 0; i < objet_form.length; i++){
url += "/" + objet_form[i].name + "/" + objet_form[i].value;
}
objet_form.action = url;
}
if (objet_form.addEventListener){
objet_form.addEventListener("submit", gestionclic, false);
} else{
objet_form.attachEvent("onsubmit", gestionclic, false);
}
</script>
But I don't think this is a good solution.
The second is to manage it with a plugin:
For the plugin, it must be declared in the bootstrap.
For example:
public function _initPlugins(){
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Application_Plugin_PRoutage());
}
with this example, the application/plugins folder, create the PRoutage.php plugin like this:
class Application_Plugin_PRoutage extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
...
}
}
and with the variable $request you have access to your data as an array with $request->getParams().
We can imagine something like this:
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$param = $request->getParams();
$what = "";
$shape = "";
if (isset($param['what']) $what = $param['what'];
if (isset($param['shape']) $shape = $param['shape'];
if ($what == "XXXX" && $shape == "YYYY"){
$request->setControllerName('other_controler')
->setActionName('other_action')
->setDispatched(true) ;
}
}
I hope it will help you

How to modify form validators from controller in Zend Framework 2?

I am working with Zend Framework 2. I have defined some validation rules within my Entity class. These work as expected without any problems.
However, when in 'edit' mode I don't want the two file upload fields to be required. I tried to do setRequired(false) for both file upload fields within my controller action but it doesn't seem to have any effect on validation, it still throws a 'file was not found' message. What do I need to so the user can submit the form successfully without uploading any files?
Appreciate any help.
for change form validation in controller, you must remove current validation and set new validation. i hope this help you:
$form = new YourForm();
$form->setData ( $yourPostedData () );
$formInputFilter = $form->getInputFilter ();
// change filter
$formInputFilter->remove ( 'your_field' );
$inputFactory = new \Zend\InputFilter\Factory();
$formInputFilter->add ( $inputFactory->createInput ( array (
'name' => 'your_field',
'required' => false
) ) );
if ($form->isValid ()) {
//...
}
You can use validation groups
The documentation states:
Zend\Form provides a proxy method to the underlying InputFilter‘s setValidationGroup() method, allowing us to perform this operation.
And all you need to do is name the fields you require validating (omit the upload element names)
$form->setValidationGroup(array('foo', 'bar'));
if ($form->isValid()) {
// $data contains just 'foo' and 'bar'
$data = $form->getData();
}
The error message I was getting 'file was not found' made me realise the issue I was having was deeper than setting the validators/filters.
The form is processed via an AJAX script using a FormData object. I added the files to the object using:
oAgencyFormData.append("cssFilename", document.getElementById('logoName').files[0]);
and the object is then passed to the AJAX call. I realised that in the case when a file is not uploaded 'undefined' is being passed to the script. So I separated it into a variable which is assigned "" if no file has been specified:
var oLogoFile = document.getElementById('logoName').files[0];
var oCssFile = document.getElementById('cssFilename').files[0];
// define defaults for file upload fields (used if nothing is uploaded)
if(typeof oLogoFile === 'undefined'){
oLogoFile = '';
};
if(typeof oCssFile === 'undefined'){
oCssFile = '';
};
Once I did this then file validators worked as expected.
I had the same problem and this is how I solved it:
$form->remove('your_field');
$center->getInputFilter()->remove('your_field');
Hope it helps!

Silverstripe CMS Loading data into form : BootstrapForm::loadDataFrom() Link to this post

I am trying to load data into a form. I am using the bootstrap-forms module from Uncle Cheese. As I understand it I would normally call $form->loadDataFrom(Customer::get()->byID(4)); but the bootstrap module structures the form differently.
//CREATE CUSTOMER FORM
public function CustomerForm() {
return BootstrapForm::create(
$this,
"CustomerForm",
FieldList::create(
TextField::create("Name","Name")
TextField::create("Surname","Surname"),
FieldList::create(
FormAction::create("AddCustomer","Add customer")
->setStyle("success")
),
RequiredFields::create(array("Name","Surname","Tel1", "Address")),
/// I think the load data method should go here but i keep getting errors
BootstrapForm::loadDataFrom(Customer::get()->byID(4)
)
)
}
Any help will be appreciated.
You need to call the loadDataFrom() function outside of the form creation to pass in a DataObject for population of the fields.
Note: In the example below each of the arguments that are passed into BootstrapForm::create() are split into variables. This tends to make the code more readable and easy if you need to alter the form arguments at a later date.
I find this a good practice rather than trying to jam everything into the one method call.
Once the data is loaded into the form we then return the form object with:
return $form;
This makes the form available to the View layer. For example in a SilverStripe *.ss template you could include this form by putting a $CustomerForm placeholder in your mark up.
Hope it helps.
//CREATE CUSTOMER FORM
public function CustomerForm(){
$fields = FieldList::create(
TextField::create("Name","Name"),
TextField::create("Surname","Surname")
);
$actions = FieldList::create(
FormAction::create("AddCustomer","Add customer")
->setStyle("success")
);
$validator = RequiredFields::create(array("Name","Surname","Tel1", "Address"));
$form = BootstrapForm::create($this, "CustomerForm", $fields, $actions, $validator);
//Load your data into the form here.
$form->loadDataFrom(Customer::get()->byID(4));
return $form;
}

Using FlashMessenger with PartialLoop in ZF view scripts

I have two questions related to the FlashMessenger view helper. Both questions are to do this code:
My action method:
private $_messages; // set to $this->_helper->FlashMessenger; in init()
public function loginAction() {
// > login validation <
// Switch based on the result code
switch ($result->getCode()) {
// > snip several cases <
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$this->_messages->addMessage("That wasn't the right password.");
break;
case Zend_Auth_Result::SUCCESS:
$this->_messages->addMessage('Logged you in successfully. Welcome back!');
$this->_helper->Redirector('index', 'home');
break;
}
// >snip<
$this->view->messages = $this->_messages->getMessages();
$this->render();
}
My layout (Zend_Layout) view script:
<?php if (isset($this->messages) && count($this->messages) > 0) {
print_r($this->messages);
//$this->partialLoop('partials/messages.phtml', $this->messages);
} ?>
Why is the message not output the first time it is set?
I have a feeling this is to do with the messenger being stored in sessions but I'm sure it's to do with my implementation.
When I submit a bad value to my form I don't get a message until I either send the form again or refresh.
What is a good way of sending this to the PartialLoop helper?
The output of the messenger is something like:
Array(
[0] => 'Message',
[1] => 'Second message' //etc.
)
But this is no good for a PartialLoop as I need to get the message (which needs each message to be an array, containing a 'message' => 'Message string' key/value pair).
Is there a better method instead of rewriting the array before submitting it to the view?
Referring to OIS I'd like to add that you can retrieve the flash-messages within the same request in which they where added to the FlashMessenger. In this case you'd have to use Zend_Controller_Action_Helper_FlashMessenger::getCurrentMessages().
In your case you'd have to change the line
$this->view->messages = $this->_messages->getMessages();
to
$this->view->messages = $this->_messages->getCurrentMessages();
Hope that helps.
Ill quote from the documentation.
10.8.4.4.1. Introduction
The FlashMessenger helper allows you
to pass messages that the user may
need to see on the next request. To
accomplish this, FlashMessenger uses
Zend_Session_Namespace to store
messages for future or next request
retrieval.
Basically, this means that yes you have to refresh the page to see the messages.
Edit for PartialLoop:
You could try this:
foreach ($array as $message) {
$newArray[]['message'] = $message;
}
But you dont have to use PartialLoop. You could send it to Partial and loop it there. Or even loop it right there in your view.

Categories