How to render a view in modal window using ajax in ZF2? - php

I try to render an action with a dedicated view in a modal window with an ajax call in Zend Framework 2.
This is my controller action :
public function myAction()
{
$htmlViewPart = new ViewModel();
$htmlViewPart->setTemplate('path/to/my/view')
->setTerminal(true)
->setVariables(['arrayVar' => ['a', 'b', 'c']]);
return $htmlViewPart;
}
The view :
<?php
foreach($arrayVar as $k => $v)
{
echo $k . ':' . $v . '<br>';
}
The js :
$(".my-modal-link").click(function() {
$('#myModal .modal-body').load($(this).data('/url/to/my/action'));
});
This not do the trick. I also tried with a JSON model too:
public function myAction()
{
$htmlViewPart = new ViewModel();
$htmlViewPart->setTemplate('path/to/my/view')
->setTerminal(true)
->setVariables(['arrayVar' => ['a', 'b', 'c']]);
$htmlOutput = $this->getServiceLocator()->get('viewrenderer')->render($htmlViewPart);
$jsonModel = new JsonModel();
$jsonModel->setVariables(['html' => $htmlOutput]);
return $jsonModel;
}
But the final render in the modal is something like :
{"html":"0:a\u003Cbr\u003E1:b\u003Cbr\u003E2:c\u003Cbr\u003E"}
Have an idea to how achieve that?

All you need is disabling the layout using setTerminal() and returning proper model from your controller to render HTML output in your modal.
In your case, you have to return a ViewModel instance. So, your first approach is correct. This should work:
$htmlViewPart = new ViewModel();
$htmlViewPart->setTemplate('path/to/my/view')
->setTerminal(true)
->setVariables(['arrayVar' => ['a', 'b', 'c']]);
return $htmlViewPart;
The second case is; you're trying to use a HTML output as json data. Try to change your ajax loading mechanism similar to this:
$(".my-modal-link").click(function() {
$.get("/url/to/my/action", function(data) {
$('#myModal .modal-body').html(data);
});
});
This will be append the rendered output (which doesnt have a layout) into modal's body. You may also want to read this for JsonModel scenario.
Hope it helps.

I found a solution.
Just create an empty layout returning content.
// Application/view/layout/ajax.phtml
<?php
echo $this->content;
And set this template in the action view
<?php
$this->layout()->setTemplate('layout/ajax');
It works now with Jquery $.load() / ViewModel strategy

Have the same problem this works...
$.get("<?php echo $this->url('your url'); ?>", function(data)
{
console.log(data);
$('#myModal .modal-body').html(data);
});

Related

Session flashdata doesn´t work on form submit

I am using the ion-auth "library" for codeigniter (https://github.com/benedmunds/CodeIgniter-Ion-Auth) and I am getting a trouble with the flashdata. This is a sumary of code:
public function reset_password($code = NULL)
{
if (!$code)show_404();
$this->user = $this->ion_auth->forgotten_password_check($code);
if ($this->user)
{
//setting the rules
if ($this->form_validation->run() == false)
{
//more code
$this->_get_csrf_nonce();
/*
One of the things this function (_get_csrf_nonce) makes is:
$this->session->set_flashdata('csrfkey', $key);
$this->session->set_flashdata('csrfvalue', $value);
*/
//The next thing is load the view with the form
}
else //form is running
{
echo "flashdata csrfkeyvalue: ".$this->session->flashdata('csrfvalue')."<br>";
die;
//more code, but not important by the moment
}
}
}
Well, the echo of $this->session->flashdata('csrfvalue') when the form is submited allways show nothing.
If I make something like:
private function _get_csrf_nonce(){
/*$this->load->helper('string');
$key = random_string('alnum', 8);
$value = random_string('alnum', 20);
$this->session->set_flashdata('csrfkey', $key);*/
$this->session->set_flashdata('csrfvalue', $value);
redirect(base_url("auth/test"));
//return array($key => $value);
}
public function test()
{
echo "flashdata csrfkeyvalue: ".$this->session->flashdata('csrfvalue')."<br>";
}
In this case... it works. The view I am using to the form is very very similar from this: https://github.com/benedmunds/CodeIgniter-Ion-Auth/blob/2/views/auth/reset_password.php
Thanks.
SOLUTION
After fighting a little, I was looking for something that could make a new request between the view of form was loaded and the form was submited... finally, I discover (I didn´t remember) a javascript that is request though a controller (to translate some texts, based on this tutorial: http://www.student.kuleuven.be/~r0304874/blog/international-javascript-files-in-codeigniter.html). I was loaded in this way:
<script src="<?=site_url('jsloader/login.js');?>" type="text/javascript"></script>
Thanks.

Codeigniter RESTful API not returning JSON

I have this application where I use Codeigniter as backend and Backbone as frontend. Now I use the RESTful API from https://github.com/philsturgeon/codeigniter-restserver. I want to fetch RSS feeds, so I created a RSS-model.php in application->models:
<?php
class Rss_model extends CI_Model
{
var $table_name = 'artist_news';
var $primary_key = 'news_id';
function get_all_rss_feeds()
{
$this->db->select($this->primary_key);
$this->db->from($this->table_name);
return $this->db->get();
}
}
?>
and then in application->controllers I created the folder api in which I created the file rss.php:
<?php
require(APPPATH.'libraries/REST_Controller.php');
class rss extends REST_Controller{
public function get_all_rss_feeds_get()
{
$this->load->database();
$this->load->model('rss_model');
$data = $this->rss_model->get_all_rss_feeds();
if($data) {
$this->response($data, 200);
} else {
$this->response(array('error' => 'Couldn\'t find any news!'), 404);
}
}
}
?>
So far so good, it returns an array of text with a lot of rss-feeds, but NOT in JSON format, which I need for my frontend.
Does anyone know what the issue is here?
Thanks in advance...
[EDIT]
My Backbone Code looks like this:
function (App, Backbone) {
var Rss = App.module();
Rss.View = Backbone.View.extend({
template: 'rss',
initialize: function() {
this.listenTo(this.collection, 'all', this.render)
},
serialize: function() {
return this.collection ? this.collection.toJSON() : [];
}
});
Rss.RssCollection = Backbone.Collection.extend({
url: function() {
return '/myproject/index.php/api/rss/get_all_rss_feeds/';
}
});
return Rss;
}
go to config/rest.php file and find this line :
$config['rest_default_format'] = 'xml';
change it to :
$config['rest_default_format'] = 'json';
I think you missed the result in return in the model please check below
function get_all_rss_feeds()
{
$this->db->select($this->primary_key);
$this->db->from($this->table_name);
return $this->db->get()->result();
}
If you are usign the Phil Sturgeon REST library you need to append the format type in the URL. Example:
http://example.com/books.json
http://example.com/books?format=json
If you want it in another format, let's say XML, you just need to pass the new format in the URI, doesn't need to change anything in your code. Example:
http://example.com/books.xml
http://example.com/books?format=xml
Further reading:
Content-Type Section - https://github.com/philsturgeon/codeigniter-restserver

Save multiple images fetched in Cakephp

I am trying to save multiple images on the server. Lets start from the beginning:
//I use this function for testing
function testSave(){
$this->_renderChart(156);
}
//This function takes chart_id as a parameter to render a proper chart.
function _renderChart($chart_id = null){
if(!$chart_id)
return false;
$chartFilterList = $this->getChartFilterListFromId($chart_id);
$this->loadChartFromId($chart_id, $chartFilterList);
$this->layout = 'analytics\chart_one.ctp';
}
The above function's view contains all the necessary scripts to render the chart. This is the part that is translating the rendered chart into base64string and saves it:
//../views/layouts/analytics/chart_one.ctp
<script type="text/javascript">
$(document).ready(function(){
saveChartAsImage('#chart1');
});
</script>
And the above function's body:
function saveChartAsImage(div){
var base64string = $(div).jqplotToImageStr();
$.ajax({
url: 'saveImage',
type: "POST",
dataType: "html",
data:"data=" + base64string
});
}
}
This is not even close to be working. Am I doing something wrong here?
If these functions are controller actions you can use $this->response->body() in controller's afterFilter() callback to get the response content and save it to file. If these are helper functions you can get the content in afterLayout() or afterRender() callbacks of the helper using $this->_View->Blocks->get('content');
I advise creating a behavior, and add the action beforeValidate();
After that make the conditions necessary to invoke the specific actions (listed in your question).
Example:
app/Model/Behavior/ChartBehavior.php
class ChartBehavior extends ModelBehavior {
// if necessary, create a setup action
public function setup(Model $Model, $settings = array()) { }
public function upload(Model $Model) {
// use the $Model->data to see all information from your form
debug($Mode->data);
// now call your functions below to upload
}
public function line_chart($chart_id = null){
//magic...
}
public function bar_chart($chart_id = null){
//magic...
}
public function pie_chart($chart_id = null){
//magic...
}
I hope it helps you.

multiple zend pagination controls via ajax and jquery

Can someone help me achieve multiple zend pagination in a view using ajax. I have managed to achieve single pagination no problem, but now i want to perform more than 1.
this is my setup:-
added to the bootstrap:-
public function _initPaginator(){
Zend_Paginator::setDefaultScrollingStyle('Sliding');
Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination_control.phtml');
}
'pagination_control.phtml' has been taken from the zend framework manual.
added to the controller:-
public function init()
{
parent::init();
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('view', 'html')
->initContext();
}
added this to the controller action:-
public function viewAction()
{
$query = $this->_em->createQueryBuilder()
->select('t')
->from('Ajfit\Entity\Ticket', 't')
->where('t.engineerFk = :engineer')
->orderBy('t.dt', 'desc')
->setParameter('engineer', $engineer)
->getQuery();
$paginator = new Paginator($query);
$adapter->getIterator();
$zend_paginator = new \Zend_Paginator($adapter);
$zend_paginator->setItemCountPerPage(3)
->setCurrentPageNumber($this->_getParam('page'));
$this->view->ticketPaginator = $zend_paginator;
}
added this to the view:-
<div>
<div id="ticket-history">
<?php
echo $this->render('profile/view.ajax.phtml');
?>
</div>
</div>
<script>
$(document).ready(function() {
$('.pagination-control').find('a').live('click', function(e) {
var link = $(this);
$('#ticket-history').load(link.attr('href'), { format: 'html' });
return false;
});
});
</script>
my 'profile/view.ajax.phtml' script contains:-
<?php
echo '<table border="0" width="100%" cellspacing="3" cellpadding="3"><tr>';
foreach($this->ticketPaginator as $ticket){
echo '<td>' . $ticket->getSubject() . '</td>';
}
echo '</tr></table>';
?>
<?php
echo $this->paginationControl($this->ticketPaginator);
?>
This all works fine, however, how would one go about adding a second or third paginator to this view for a different doctrine entity?
Any help would be much apprieciated.
Thanks
Andrew
for that you have to use multiple addActionContext in init()
$this->_helper->ajaxContext->addActionContext('view', 'html')->initContext();
$this->_helper->ajaxContext->addActionContext('list', 'html')->initContext();
and you can continue
add action in controller as listAction() for paginator create file as list.ajax.phtml also and add required code inside them
This problem can be resolved if you manipulate the pagination links to let it call the other action.
For example: In the View Part, you can use the fourth parameter of the paginationControl method to define the links which refers to another action. This link should then be called in pagination_control.phtml.

How do I use a controller within a controller?

I am using Kohana 3.2 and I am having problems calling the ouput of a controller in another controller.
What I want...
In some pages I have got a menu, and in others I don't. I want to use make use of the flexability of the HMVC request system. In the controller of a page I want to call another controller which is responsible for the creation of the menu.
What I have a the moment:
file menu.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Menu extends Controller
{
private $_model = null;
public function __construct(Request $request, Response $response)
{
parent::__construct($request, $response);
$this->_model = Model::factory('menu');
}
public function action_getMenu()
{
$content = array();
$content['menuItems'] = $this->_model->getMenuItems();
// Render and output.
$this->request->response = View::factory('blocks/menu', $content);
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
}
}
somepage.php
public function action_index()
{
$this->template->title = 'someTitle';;
$contentData['pageTitle'] = 'someTitle';
$contentData['contentData'] = 'someData';
#include the menu
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
$this->template->content = View::factory('pages/somePage', $contentData);
$view = $this->response->body($this->template);
$this->response->body($view);
}
If I uncomment the following line in menu.php, I see the menu rendered:
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
So I guess that part is alright. The problem is in the following line in somepage.php:
$menuBlock = Request::factory('menu/getMenu')->execute();
This gives me back a response object. Whatever I do, I do not get the output in $this->template->menu.
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
What must I do to have $this->template->menu contain the view, so I can use it correctly?
I hope this all makes sense. This is the way I would like to do it, but maybe I am completely on the wrong track.
I would do it this way:
class Controller_Menu extends Controller
{
public function action_build()
{
// Load the menu view.
$view = View::factory('navigation/menu');
// Return view as response-
$this->response->body($view->render());
}
}
In your controller get the menu as follows:
// Make request and get response body.
$menu = Request::factory('menu/build')->execute()->body();
// e.g. assign menu to template sidebar.
$this->template->sidebar = Request:.factory('menu/build')->execute()->body();
I would not use the __construct method in your controllers. Use before() instead, this is sufficient for most of the problems (for example auth):
public function before()
{
// Call aprent before, must be done here.
parent::before();
// e.g. heck whether user is logged in.
if ( !Auth::instance()->logged_in() )
{
//Redirect if not logged in or something like this.
}
}
I found the answer to my problem in less than an hour after asking.
I just forgot to put it here.
In somePage.php change :
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
To:
$this->template->menu = Request::factory('menu/getMenuBlock')->execute()->body();
And in menu.php change:
$this->request->response = View::factory('blocks/menu', $content);
To:
$request = View::factory('blocks/menu', $content);
$this->response->body($request);
I hope this will help someone else.

Categories