0
votes

I am writing a custom component. I have the view employees. Under this view, I have two layouts, default and modal.

I have a menu item in the toplevel of the main menu, Employees that points to my employee view:

index.php?option=com_mycomponent&view=employees which resolves to domain.com/joomla/employees and displayes the default view as expected.


Now, inside my component I want to link to the modal view, and I do so using JRoute and this url:

index.php?option=com_mycomponent&view=employees&layout=modal

Which resolves to

domain.com/joomla/employees/modal

And produces this error:

500 - View not found [name, type, prefix]: modal, html, mycomponentView

If I visit index.php using index.php?option=com_mycomponent&view=employees&layout=modal my modal view is displayed.

I have also found that visiting domain.com/joomla/employees/employees/modal displays the correct layout. It is as if joomla is forgetting what view is associated with the menu item at /joomla/employees, and instead looks for the view "modal" unless the extra "employees" is provided in the url.

Also worth noting, domain.com/joomla/employee?layout=modal works fine as well.


Here is what I have for my router.php. This was file was generated for me using the component generator at j-cook.pro.

<?php
defined('_JEXEC') or die;

function MycomponentBuildRoute(&$query){

    $segments = array();
    if(isset($query['view']))
    {
        $view = $query['view'];
        $segments[] = $view;
        unset( $query['view'] );
    }

    if(isset($query['layout']))
    {
        $segments[] = $query['layout'];
        unset( $query['layout'] );
    }


    if(isset($query['id']))
    {
        if(in_array($view, array('edit','view','view','editfacility','view','edit','client','editclient','viewposition','editposition','edit','view','edit','view','view','edit','view','edit','view','edit','view','edit')))
        {
            $segments[] = (is_array($query['id'])?implode(',', $query['id']):$query['id']);
            unset( $query['id'] );
        }
    };


    return $segments;
}


function MycomponentParseRoute($segments)
{
    $vars = array();


    $vars['view'] = $segments[0];

    $nextPos = 1;
    if (isset($segments[$nextPos]))
    {
        $vars['layout'] = $segments[$nextPos];
        $nextPos++;
    }

    if(in_array($vars['view'], array('edit','view','view','editfacility','view','edit','client','editclient','viewposition','editposition','edit','view','edit','view','view','edit','view','edit','view','edit','view','edit'))
       && isset($segments[$nextPos]))
    {
        $slug = $segments[$nextPos];
        $id = explode( ':', $slug );
        $vars['id'] = (int) $id[0];

        $nextPos++;
    }

    return $vars;
}
1
Please include a copy of your router.php in the root directory of the component (/components/com_mycomponent/router.php). This file handles the parsing and building of the SEF urls and needs to be fixed to handle this case! - David Fritsch
Hey! Thanks a lot! I hadn't even looked at that file until now. I edited the question to include the contents. Hopefully this will get me on the right track to figuring it out, but I would greatly appreciate any more insight you can provide. Thanks again. - Jeffrey Ray

1 Answers

1
votes

So it is hard to provide an exact answer for this without knowing all the different ways that you want to have urls be parsed. But I will try to give a hint at what will solve this present situation (without hopefully introducing too many new issues!)

The basic issue is that the BuildRoute side does not get a view value so it is not included in the url. On the one hand it is not necessary, because it is in the menu. But it makes it a little harder to parse, so option one is to force there to be a view if you can by changing the top function to start like this:

function MycomponentBuildRoute(&$query){

  $segments = array();
  if(isset($query['view']))
  {
      $view = $query['view'];
      $segments[] = $view;
      unset( $query['view'] );
  }
  else
  {
      $app = JFactory::getApplication();
      $menu = $app->getMenu();
      $active = $menu->getActive();
      if ($view = $active->query['view']) {
        $segments[] = $view;
      }
  }
...

In this way, if there is a menu item for this and it has a view we will tack it on. This should generate domain.com/joomla/employees/employees/modal.

You could also probably do this logic on the parse side too. This would go instead of the other option above:

function MycomponentParseRoute($segments)
{
    $vars = array();

    $app = JFactory::getApplication();
    $menu = $app->getMenu();
    $active = $menu->getActive();
    if ($active->query['view']) {
        $vars['layout'] = $segments[0];
        $nextPos = 1;
    } else {
        $vars['view'] = $segments[0];
        $nextPos = 1;
        if (isset($segments[$nextPos]))
        {
            $vars['layout'] = $segments[$nextPos];
            $nextPos++;
        }
    }

    ... continue with final check for id

I would probably use the second option but both are an option. By the way, you are also likely to run into issues if you try to use an id without setting a layout.