Feature #41439

Argument to add an active-state class to "f:link.action"

Added by Michael Gerdemann almost 3 years ago. Updated over 2 years ago.

Status:Rejected Start date:2012-09-28
Priority:Should have Due date:
Assigned To:Bastian Waidelich % Done:

0%

Category:ViewHelpers
Target version:-
Has patch:No

Description

If the rendered template exactly matches the action, it would be great if you would have the ability to automatically add a "active" class.

History

#1 Updated by Michael Gerdemann almost 3 years ago

Here is my edited render class:

/**
     * Render the link.
     *
     * @param string $action Target action
     * @param array $arguments Arguments
     * @param string $controller Target controller. If NULL current controllerName is used
     * @param string $package Target package. if NULL current package is used
     * @param string $subpackage Target subpackage. if NULL current subpackage is used
     * @param string $section The anchor to be added to the URI
     * @param string $format The requested format, e.g. ".html" 
     * @param string $addActiveClass Add an active-class
     * @param array $additionalParams additional query parameters that won't be prefixed like $arguments (overrule $arguments)
     * @param boolean $addQueryString If set, the current query parameters will be kept in the URI
     * @param array $argumentsToBeExcludedFromQueryString arguments to be removed from the URI. Only active if $addQueryString = TRUE
     * @return string The rendered link
     * @throws \TYPO3\Fluid\Core\ViewHelper\Exception
     * @api
     */
    public function render($action = NULL, $arguments = array(), $controller = NULL, $package = NULL, $subpackage = NULL, $section = '', $format = '', $addActiveClass = '', array $additionalParams = array(), $addQueryString = FALSE, array $argumentsToBeExcludedFromQueryString = array()) {
        $uriBuilder = $this->controllerContext->getUriBuilder();

        try {
            $uri = $uriBuilder
                ->reset()
                ->setSection($section)
                ->setCreateAbsoluteUri(TRUE)
                ->setArguments($additionalParams)
                ->setAddQueryString($addQueryString)
                ->setArgumentsToBeExcludedFromQueryString($argumentsToBeExcludedFromQueryString)
                ->setFormat($format)
                ->uriFor($action, $arguments, $controller, $package, $subpackage);
            $this->tag->addAttribute('href', $uri);
        } catch (\TYPO3\FLOW3\Exception $exception) {
            throw new \TYPO3\Fluid\Core\ViewHelper\Exception($exception->getMessage(), $exception->getCode(), $exception);
        }

        if(
            (
                !isset( $action )
                ||
                ( isset( $action ) && $this->controllerContext->getRequest()->getControllerActionName () == $action )
            )
            &&
            (
                !isset( $controller )
                ||
                ( isset( $controller ) && $this->controllerContext->getRequest()->getControllerName() == $controller )
            )
            &&
            (
                !isset( $package )
                ||
                ( isset( $package ) && $this->controllerContext->getRequest()->getControllerPackageKey () == $package )
            )
            &&
            (
                !isset( $subpackage )
                ||
                ( isset( $subpackage ) && $this->controllerContext->getRequest()->getControllerSubpackageKey () == $subpackage )
            )
        ) {
            $classTag = $this->tag->getAttribute('class');
            $this->tag->addAttribute('class', ( isset($classTag) && !empty( $classTag ) ? $classTag . ' ' : '' ) . $addActiveClass );
        }

        $this->tag->setContent($this->renderChildren());
        $this->tag->forceClosingTag(TRUE);

        return $this->tag->render();
    }

#2 Updated by Bastian Waidelich over 2 years ago

  • Status changed from New to Rejected
  • Assigned To set to Bastian Waidelich

As discussed on IRC: This behavior is too specific to be implemented into a core ViewHelper in my opinion. Besides it probably won't work reliably in nested requests (plugins, widgets, ...).
Therefore I suggested to either subclass the link.action ViewHelper and adjust it as needed:

 1namespace Your\Package\ViewHelpers\Link;
 2
 3class ActionViewHelper extends \TYPO3\Fluid\ViewHelpers\Link\ActionViewHelper {
 4
 5    public function render($action = NULL, $arguments = array(), $controller = NULL, $package = NULL, $subpackage = NULL, $section = '', $format = '',  array $additionalParams = array(), $addQueryString = FALSE, array $argumentsToBeExcludedFromQueryString = array()) {
 6
 7        if ($this->matchesCurrentRequest($action, $arguments, $controller, $package, $subpackage)) {
 8            $cssClass = 'active';
 9            if ($this->hasArgument('class')) {
10                $cssClass .= ' ' . $this->arguments['class'];
11            }
12            $this->tag->addAttribute('class', $cssClass);
13        }
14
15        return call_user_func_array('parent::render', func_get_args());
16    }
17
18    protected function matchesCurrentRequest($action, $arguments, $controller, $package, $subpackage) {
19        // TODO compare arguments with $this->controllerContext->getRequest() and return TRUE if they match
20    }
21
22}

Alternatively, you could create a subclass of the AbstractConditionViewHelper (see if ViewHelper for an example) that compares its arguments to the current request.
This one could be used as follows:

1<f:link.action action="foo" class="{x:ifCurrentRequest(action: 'foo', then: ' active')}">Link</f:link.action>

#3 Updated by Bastian Waidelich over 2 years ago

Bastian Waidelich wrote:

BTW: If you want to render a menu with active/inactive menu items this snippet might help you: https://gist.github.com/4223855

Also available in: Atom PDF