I'm using Laravel 4 for my website, and would like to check on every page load if user has seen a popup, and if not - show the popup to the user.
I don't want to do that in every controller, is there a place where can I put the code, so it's checked before every page is loaded?
You can create a filter to check if the popup is shown.
// app/filters.php
Route::filter('popup.shown', function()
{
// Your check logic here
});
Then, you could use that filter in your routes, controllers or a base controller which you could extend to have this functionality:
class PopupController extends BaseController {
public function __construct()
{
$this->beforeFilter('popup.shown');
}
}
Then, extend this controller:
class MyController extends PopupController {
public funcion getIndex()
{
// this will run the `popup.shown` filter
}
}
You can read more about beforeFilter() here:
http://laravel.com/docs/controllers#controller-filters
Another approach would be to use the App::before() event, so the check would be done on every request. However, I don't recommend this one as it's not flexible and you will have to modify it soon or later.
I would approach this via a view/template style. Although if you use a lot of templates that don't show this popup then maybe the filter method suggested by Manuel Pedrera is best.
In global.php or some bootstrap file you can set a view variable that is injected automatically. http://laravel.com/docs/responses#views
// Perform popup logic
View::share('showPopup', $logicResult);
And then in the various layouts you want to include this popup you can check for the variable within the view. http://laravel.com/docs/templates
#if ($showPopup)
<div class="popup">Popup</div>
#endif
The advantage of this is that you do not have to include the variable to show/hide the popup for every View::make() call.
Related
My EmberJS app has a couple of actions (triggered by buttons) that require a view/DOM manipulation as well as setting a state in the controller, followed by a model update. The way I do this, it does not appeal to my programming aesthetics. It gets the job done, but it doesn't look good :(
Here is a gist of how I do things :
<button {{action 'whatever' target='view'}}></button>
App.MyView = Ember.View.extend({
actions:{
whatever:function(){
var ctrl = this.get('controller');
ctrl.set('property',value); // arbitrary example of setting a controller property through it's view
ctrl.controllerMethod(); // invoking a controller method through the view
**// do some DOM manipulation**
}
}
});
Naturally, I can wrap whatever controller related steps I am performing in the view in a controller method and invoke that method through the view, but IMO that's just equally ugly. The view shouldn't really be invoking a controller method like how I have done. Unfortunately, this specific action requires a DOM manipulation as well as setting some state and performing an action in the controller.
I am not sure what is the recommended way of performing this. Can anyone enlighten ?
I suggest you handle the action from the controller. I noticed you're setting a property. You can use that to signal something to the view and then do the DOM manipulation within the view.
App.MyView = Ember.View.extend({
function () {
**// do some DOM manipulation**
}.observe('controller.property');
});
The way I think about it is that UI 'actions' are mapped to a business event (e.g. addClient instead of click), then as a result of that something happens that could change properties of the model, controller. As a result of those changes the view might need to update directly, ideally through a binding, but sometimes is needed to modify the DOM manually.
as #LukeMelia said in his comment you should really handle the changes in your controller and update your view (if you need to?) via databinding.
so, you would just omitt the target="view" argument from your view helper and Ember will look for the proper action in the nearest controller, bubbling all the way up to the route, and so on.
a simple code snippet (with what you provided in your first post) would look like:
Handlebars Template:
<button {{action someAction}}>Fire!</button>
Ember.Controller:
App.MyController = Ember.ObjectController.extend({
myProperty: 'cool',
printMyCoolness: function () {
console.log("I'm using Ember.js!");
},
actions: {
someAction: function () {
this.set('myProperty', 'set on fire!');
this.printMyCoolness();
}
}
});
I'm developing a custom mvc component for Joomla 2.5.
For my admin section I included a "New" button in the toolbar.
By clicking this button I want to display a separate form with less
fields. So far everything works out but the buttons of the view's
toolbar won't redirect (i.e. 'Cancel')
To redirect the task 'add' I added an override of the method "add()"
to my controller:
class ArchitectProjectControllerArchitectProject extends JControllerForm
{
public function add()
{
JRequest::setVar('layout', 'add');
$result = parent::add();
return $result;
}
}
I don't know if I'm on the right track. Probably someone can give me a hint?
If you wish to redirect for example on 'Cancel' then try the following in the controller:
public function cancel()
{
$this->setRedirect('index.php?option='.$this->option.'&view=yourview');
}
I have a menu on my page that is loaded on every page. The menu data is fetched from the database through a model. My first thought was to call the model from the controller, and then pass it to the view on every page. But that results in "messy" code, if i ever forget to pass the menu data to the view, it will result in an ugly error (or just no menu items).
So i came up with the solution of fetching the menu items through a helper, and then just call the helper function from the view. It makes more sense, because i only have the code in one place (the menu view).
My views are set up in this way: Controller calls "page" view which then loads the header view, menu view, the appropriate content view, and lastly the footer view. The helper is only called from one place, the menu view.
Normally you can't even load models from helpers, but i did a workaround using $i = get_instance(); and then loading the model through that instance; $i->load->model().
I have a feeling this is not the way to go, but are there any better ways?
Edit: To put it in a better way:
I want:
view -> get data -> display
not:
controller -> get data -> pass to view -> display
I'm just not sure if that's "Ok" to do, since it disregards the MVC model completely.
So I found a quick example to cut-n-paste (in this case I have a model called login autoloaded, but you can of course do that manually)
In the file core\MY_Controller.php
class Admin_Controller extends CI_Controller
{
protected $login_ok;
public function __construct()
{
parent::__construct();
/* --- Check if user is logged in --- */
$this->config->load('adldap', TRUE);
$data->login_ok = $this->login->check_login(TRUE);
$this->load->vars($data);
}
}
If you then extend your controller with this. You will have $login_ok available in your view.
This way you can be sure that the required variables are always prepared and you only have to write the code in one place
I think that the solution is easier than you think.
If now you're doing something like this in your helper:
create_menu()
{
$menu_items = $this->db->query('')->result();
// creating the menu here
}
You could just change the function to accept input like this and still follow the MVC pattern.
Helper
create_menu($input)
{
$menu_items = $input;
// creating the menu here
}
Model:
get_menu_data()
{
$menu_items = $this->db->query('')->result();
}
Does this make sense?
Edit:
This is the way I did it on one of the projects:
I extended my standard controller. Within the constructor of that controller I called the model and grabbed the data:
$this->menu_items = $this->some_model->get_menu_items();
Within a view nav.php:
if(!empty($this->subnav_item))
{
// Generate menu
}
This way the MVC is intact, but I dont have to worry about passing variables.
EDIT 2
How to extend the standard controller:
Create a file MY_Controller.php in application/core
class MY_Controller extends CI_Controller {
public $menu_items = '';
function __construct()
{
parent::__construct();
$this->load->model('some_model_that_you_always_use');
$this->load->library('some_library_that_you_always_use');
$this->menu_items = $this->some_model->get_menu_items();
}
}
When you create a new controller, you extend MY_Controller instead of CI_Controller like this:
class Something extends MY_Controller {
}
Keep in mind that nothing about the MVC pattern prohibits a View from contacting a Model directly. That's just a convention that seems common with CodeIgniter.
I suggest that in this case, your menu view should load the menu data directly from the menu model.
I have a view that could be called from any of 3 actions from one controller.
But, that view should be slightly different depending on what action caused it (it should display 3 icons or 2 or one depending on action called). Can I check in the view what action caused it so I can use if statement to check whether display each icon or not?
Thank you.
Of course, you can pass action value directly to the view:
$this->template->action = Request::current()->action();
But View should not know anything about Request properties, its a Controller logic. I suggest you to pass special flags from your actions:
public function action_show1()
{
// show only one icon
$this->template->icons = array('first');
}
public function action_show2()
{
// show another two icons
$this->template->icons = array('second', 'third');
}
public function action_showall()
{
// show all icons
$this->template->icons = array('first', 'second', 'third');
}
Or set special flag (variable) for every icon.
I'm using fancybox plugin to load a page and execute some code. The problem is that at times theres always the chance that someone would click on a link thats meant to be opened in a fancybox window before the page loads completely and the fancybox plugin is set up opening the page looking messed up in an complete browser window. Is there a way to tell whether an HTTP request is via ajax or not so I can set up my layouts accordingly.
I'm using the zend framework and have defined two layouts one for pages opened with fancybox and one is the regular page layout.
In you actions you can use isXmlHttpRequest() method to detect ajax request. For example, you could do:
public function onlyajaxAction() {
if ($this->getRequest()->isXmlHttpRequest()) {
// handel ajax request.
} else {
// if not an ajax request, e.g. throw an exception or whatever
}
}
You can check the X-Requested-With header, which is set to XMLHttpRequest by many Javascript libraries.
If you need to use a same action in different context to provide the according result, you may use the contextSwitcher() action helper (or ajaxContext())
<?php
class YourController extends Zend_Controller_Action
{
public function init ()
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('do-something', 'json')
->initContext();
}
public function doSomethingAction ()
{
// some logic here
$this->view->data = $data;
}
}
Use the ?format=json parameter to switch context, in case of JSON ZF will take care to convert $this->view->data to JSON for you, it will also disable layout, etc.