I used the following code to display the menu items.
Here by default the 'Home' link should be activated. So that i used the code
active' => $this->id =='default' ? true : false
$this->widget('zii.widgets.CMenu',array(
'linkLabelWrapper' => 'span',
'items'=>array(
array('label'=>'Home', 'url'=>array('post/index'),'active'=>$this->id=='default'?true:false),
array('label'=>'About', 'url'=>array('site/page', 'view'=>'about'),'active'=>$this->id=='about'?true:false),
array('label'=>'Test', 'url'=>array('site/page', 'view'=>'test')),
array('label'=>'Contact', 'url'=>array('site/contact')),
array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('site/logout'), 'visible'=>!Yii::app()->user->isGuest)
),
));
I referred the url http://www.yiiframework.com/doc/api/1.1/CMenu#activateItems-detail
But i dont know how to use these parameters. Please help
Not the Yii way, but the (simpler) jQuery way:
// find menu-item associated with this page and make current:
$('a').each(function(index, value) {
if ($(this).prop("href") === window.location.href) {
$(this).addClass("current-page");
}
});
The code you give will be typically found inside a view. The documentation for view states that
Inside the view script, we can access the controller instance using
$this. We can thus pull in any property of the controller by
evaluating $this->propertyName in the view.
So, we have established that in the current context, $this->id refers to the CController::id property. This id will typically be the prefix of your controller's class name. For example, inside MyController you will have $this->id == "my".
With all this in mind, you can now tell that active will be true if and only if the current view is rendered from inside a controller named DefaultController. However, from the url property of that menu item we see that the associated controller for that action (assuming default routing) is PostController. So the $this->id == "default" idea is faulty.
If you want to make the "Home" item active whenever any action in your PostController is running, you should change this to $this->id == "post". Normally it should not be necessary to do this, because the activateItems property (which defaults to true) used with default routing will take into account both the controller id and the current action to determine which menu item to make active.
if you have some advanced link structure, put method below in Controller
/**
* Checks if the current route matches with given routes
* #param array $routes
* #return bool
*/
public function isActive($routes = array())
{
$routeCurrent = '';
if ($this->module !== null) {
$routeCurrent .= sprintf('%s/', $this->module->id);
}
$routeCurrent .= sprintf('%s/%s', $this->id, $this->action->id);
foreach ($routes as $route) {
$pattern = sprintf('~%s~', preg_quote($route));
if (preg_match($pattern, $routeCurrent)) {
return true;
}
}
return false;
}
//usage
'items'=>array(
array('label'=>'Some Label', 'url'=>array('some/route'),'active'=>$this->isActive(array(
'some/route',
'another/route',
)),
),
I used this way:
array('label'=>'Contact', 'url'=>array('site/contact'), 'active'=>strpos(Yii::app()->request->requestUri, Yii::app()->createUrl('site/contact'))===0)
The menu will work as we use default pages as site/contact, site/login
But many times it will not work for the module url.
suppose i have module user and i had login action in login controller, so i can do below thing form menu as how menu item gets active defined below.
array('label'=>Yii::t('frontend','Login'), 'url'=>array('/user/login/login'), 'visible'=>Yii::app()->user->isGuest), // Working, Login tag activated on login page
array('label'=>Yii::t('frontend','Login'), 'url'=>array('/user/login'), 'visible'=>Yii::app()->user->isGuest), // Not working, Login tag not activated on login page
So, we can have problem to beautify url..
For yiistarterkit just add this code in the _base.php file:
function isActive($routes = array())
{
if (Yii::$app->requestedRoute == "" && count($routes) == 0){
return true;
}
$routeCurrent = Yii::$app->requestedRoute;
foreach ($routes as $route) {
$pattern = sprintf('~%s~', preg_quote($route));
if (preg_match($pattern, $routeCurrent)) {
return true;
}
}
return false;
}
And then use:
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-left'],
'items' => [
['label' => \Yii::t('frontend', 'Home'), 'url' => ['/'], 'active'=>isActive()],
['label' => \Yii::t('frontend', 'Services'), 'url' => ['/services'], 'active'=>isActive(['services'])],
]
]);
Take as a base the file yiisoft/yii2-boostrap/nav.php function renderItem():
...
if ($this->activateItems && $active) {
Html::addCssClass($options, 'active');
}
return Html::tag('li', Html::a($label, $url, $linkOptions) . $items, $options);
And modify $option on $linkOption for a link.
Html::addCssClass($linkOptions, 'active');
As result active class will be added to a.class, instead li.class
Related
I am using codeigniter I have an edit page which shows me all information of a vacancy.
The (Vacancy) controller method to load this view looks like this, it makes sure all data is preloaded.
public function editVacancy($vacancyid)
{
$this->is_logged_in();
$this->load->model('vacancy/vacancies_model');
// Passing Variables
$data['title'] = 'Titletest';
$data['class'] = 'vacancy';
$orgadminuserid = $this->vacancies_model->getOrgAdminUserId($vacancyid);
if ((!is_null($orgadminuserid)) && ($this->auth_user_id == $orgadminuserid[0]->user_id)) {
$data['vacancyid'] = $vacancyid;
$data['vacancy'] = $this->vacancies_model->get($vacancyid);
$data['test'] = $this->session->flashdata('feedbackdata');
$partials = array('head' => '_master/header/head', 'navigation' => '_master/header/navigation_dashboard', 'content' => 'dashboard/vacancy/edit_vacancy', 'footer' => '_master/footer/footer');
$this->template->load('_master/master', $partials, $data);
}
}
In this view i have different forms for updating different sections.
Every form submit goes to a different method in my 'Vacancy' controller.
public function saveGeneralInfo()
{
$this->is_logged_in();
$this->load->model('vacancy/vacancies_model');
$vacancyid = $this->input->post('vacancyid');
$vacancyUpdateData = $this->vacancies_model->get($vacancyid);
$result = $this->vacancies_model->update($vacancyid, $vacancyUpdateData);
if ($result) {
$feedbackdata = array(
'type' => 'alert-success',
'icon' => 'fa-check-circle',
'title' => 'Success!',
'text' => 'De algemene vacature gegevens zijn geupdate.'
);
$this->session->set_flashdata('feedbackdata', $feedbackdata);
redirect("dashboard/vacancy/editVacancy/" . $vacancyid);
}
}
}
Where I indicated in my code "//HERE ..." is where I would want the feedback message parameter to pass on to my 'main controller method' which loads the view with the prefilled data. (editVacancy).
Is there a clean way to do this?
EDIT:
I tried using flashdata, i updated the code to have the flashdata inserted.
However when i do a var_dump($test); in my view, it remains null.
EDIT 2:
I noticed when i put my $_SESSION in a variable in my editVacancy controller method (which is being redirected to) and var_dump it in my view that this does not contain the ci_vars with the flashdata in.
Instead of using set_header you can use simple redirect function for it.
redirect("dashboard/vacancy/editVacancy/".$vacancyid);
I use this partial to generate my submenu.
<?php foreach ($this->container as $page): ?>
<?php foreach ($page->getPages() as $child): ?>
<a href="<?php echo $child->getHref(); ?>" class="list-group-item">
<?php echo $this->translate($child->getLabel()); ?>
</a>
<?php endforeach; ?>
<?php endforeach; ?>
Which is called like this:
$this->navigation('navigation')->menu()->setPartial('partial/submenu')->render();
But when i render the menu the "$child->getHref()" renders the url without the needed "slug/id" parameter.
I tried to create the url with "$this->url()" in ZF1 you could pass the params in an array to the partial but in ZF2 that doesn't seem to work anymore.
Can anybody tell me how to add the params to the menu urls?
Thanks in advance!
PS!
I'm not referring to $this->Partial, i'm talking about $this->navigation('navigation')->menu()->setPartial('partial/submenu')->render() which apparently doesn't support a param array.
If I'm understanding your question, yes, you can pass params to partials. Example:
<?php echo $this->partial('partial.phtml', array(
'from' => 'Team Framework',
'subject' => 'view partials')); ?>
See http://framework.zend.com/manual/2.3/en/modules/zend.view.helpers.partial.html
I'm not sure this completely solves your issue, since you are not showing what the menu helper is. Is it your own view helper? Are you saying that setPartial method only accepts one argument?
All that said, have you considered Spiffy Navigation?
https://github.com/spiffyjr/spiffy-navigation
It's been sometime since this question was asked, however today I came across the same problem (using version 2.4).
If you have a segment route to be included within the menu that requires some parameters there is no way to pass these through to the navigation's view partial helper.
The change I've made allows a ViewModel instance to be passed to the menu navigation helper's setPartial() method. This view model will be the context for the navigation's partial template rendering; therefore we can use it to set the variables we need for the route creation and fetch them just like within other views using $this->variableName.
The change requires you to extend the Menu helper (or which ever navigation helper requires it).
namespace Foo\Navigation;
use Zend\Navigation\AbstractContainer;
use Zend\View\Model\ViewModel;
class Menu extends \Zend\View\Helper\Navigation\Menu
{
public function renderPartial($container = null, $partial = null)
{
if (null == $container) {
$container = $this->getContainer();
}
if ($container && $partial instanceof ViewModel) {
$partial->setVariable('container', $container);
}
return parent::renderPartial($container, $partial);
}
public function setPartial($partial)
{
if ($partial instanceof ViewModel) {
$this->partial = $partial;
} else {
parent::setPartial($partial);
}
return $this;
}
}
Because this extends the default implementation of the helper updated configuration is required in module.config.php to ensure the extend class is loaded.
'navigation_helpers' => [
'invokables' => [
'Menu' => 'Foo\Navigation\Menu',
],
],
The menu helper will then accept a view model instance.
$viewModel = new \Zend\View\Model\ViewModel;
$viewModel->setTemplate('path/to/partial/template')
->setVariable('id', $foo->getId());
echo $this->navigation()
->menu()
->setPartial($viewModel)
->render();
The only change in the actual partial script will require you to create the URL's using the URL view helper.
foreach ($container as $page) {
//...
$href = $this->url($page->getRoute(), ['id' => $this->id]);
//...
}
I have a couple of different 'items' on my website that I am building with cakePHP, for instance a Recipe and a ShoppingList.
I want certain items in my view (e.g. update and delete functionality links) to only be visible to the person who uploaded that item.
I want to add a function that would compare any given id to the currently logged in user's id. It would look something like this:
public function compareUser($id){
if(!empty($this->userInfo) && $this->userInfo['User']['id'] == $id){
return true;
}
}
$this->userInfo is set in beforeFilter:
$this->userInfo = $this->User->find('first', array('conditions' => array('id' => $this->Auth->user('id'))));
I have tried putting it in my appController, but that doesn't seem to work.
How can I implement this properly? Thanks!
This is best done using the isAuthorized($user) method.
All the information about your current user is stored in $this->Session->read('Auth.User') (this retrieves the full array, if you just wanted to get their 'id' you use $this->Auth->user('id') as you already did).
From the above it should hopefully be clear that normally you don't need to retrieve the user's details through an extra query as they are already stored in the Auth component of the session :)
Make sure in the setup for your Auth component you have 'authorize' => 'controller' and add the following to your AppController:
public function isAuthorized($user) {
//I want the default to be allow the user access so I will return true
return TRUE;
}
Then add the following to your RecipesController (and ShoppingListsController if you want the same thing there):
public function isAuthorized($user) {
if ($this->action === 'update' || $this->action === 'delete') {
$recipe = $this->Recipe->find(
'first',
'conditions' => array(
'id' => $this->params['pass'][0]
)
'fields' => array(
'user_id'
)
);
if ($this->Auth->user('id') == $recipe['Recipe']['user_id']) {
return TRUE;
}
else {
return FALSE;
}
}
return parent::isAuthorized($user);
}
Now if someone tries to access www.yourDomain.com/recipes/update/2 or www.yourDomain.com/recipes/delete/2 it will check if the current user's id is 2, if it is you're good to go, if not then it blocks them from that page.
Edit:
Easiest way to have a method accessible from all places I would suggest putting it in the AppModel that way all your models will inherit it:
//inside AppModel
public function isOwnedBy($id) {
if (AuthComponent::user('id) == $id) {
return TRUE;
}
return FALSE;
}
this is a handler for building menu
new MenuItem('Owner', lang('Owner'), assemble_url('Owner'), get_image_url('navigation/Company.gif')),
new MenuItem('Client', lang('Client'), assemble_url('Client'), get_image_url('navigation/people.gif')),
One system module class in which i've mapped the route
$router->map('Owner', 'Owner','null', array('controller' => 'companies', 'action' => 'index_owner'));
$router->map('Client', 'Client','null', array('controller' => 'companies', 'action' => 'index_client'));
which calls the controller class in which methods are defined with hte name index_client,index_owner...both method has same code.
function index_client(){
if(Company::canAdd($this->logged_user)) {
$this->wireframe->addPageAction(lang('New Company'), assemble_url('people_companies_add_client'));
} // if
if($this->request->isApiCall()) {
$this->serveData(Companies::findByIds($this->logged_user->visibleCompanyIds()), 'companies');
} else {
$page = (integer) $this->request->get('page');
if($page < 1) {
$page = 1;
} // if
list($companies, $pagination) = Companies::paginateActive($this->logged_user, $page, 30);
$this->smarty->assign(array(
'companies' => $companies,
'pagination' => $pagination,
));
} // if
} // index */
Which inturn calls smarty template named index_owner,index_client.
I want that only one template should be called that is "index" because same things are being displayed only one flag in template is checked "is_owner" and according to that display of company is done..please tell me how flow goes like handlers,controller,module,view ??????
You must assign the METHOD magic constant to smarty resource.
After you do this, customize Smarty::fetch method to catch and renderize if this attribute is seted.
If you has using url rewrite and method name is into url. You can get this through the Smarty.
This feature is native in zend framework mvc implementation. Check this.
Let's say, that we have:
$pages = array(
array(
'controller' => 'controller1',
'label' => 'Label1',
),
array (
'controller' => 'controller2',
'label' => 'Label2'
),
);
$container = new Zend_Navigation($pages);
When user clicks Label1, controller1/index action is rendered and Label1 becomes active state - everything is ok.
On this page I have many links, such as: controller1/action1, controller1/action2, etc
When one of these links is clicked, Label1 looses active state.
I understand, that I can add all sub-pages into Zend_Navigation, but there are plenty of these pages and I never need it anywhere for navigation, so, I'd prefer to have something like:
public function init()
{
$this->view->navigation()-> ... get item by label ... -> setActive();
}
inside controller1. Is it possible?
Your init method is very close!
$page = $this->view->navigation()->findOneByLabel('Your Label'); /* #var $page Zend_Navigation_Page */
if ( $page ) {
$page->setActive();
}
I think this is exactly what he is looking for:
Simply paste this into your menu.phtml or any .phtml where you print your menu:
// apply active state to all actions of controller
$controller = Zend_Controller_Front::getInstance()->getRequest()->getControllerName();
$page = $this->navigation()->findOneByController($controller); /* #var $page Zend_Navigation_Page */
if ( $page ) {
$page->setActive();
}
echo $this->navigation()->menu();
Of course you need to init first a navigation structure with Zend_Navigation_Page_Mvc pages.
Somehow this does not work for me with url pages...