laravel / ideas

Issues board used for Laravel internals discussions.
938 stars 28 forks source link

[Proposal] Helper function for conditionally joining class names together #1824

Open obaydmir opened 5 years ago

obaydmir commented 5 years ago

This feature request is inspired by a package named classnames for JavaScript maintained by Jed Watson. It would be helpful for laravel to also have a helper like this so conditionally rendering class names becomes less verbose.

This helper returns a string containing all class names which do not have a condition set as element value or have resulted in true boolean value.

The basic implementation of this helper would be:

if (! function_exists('cn')) {
    /**
     * Conditional return classnames.
     *
     * @param array $list
     * @return string
     */
    function cn(array $list) {

        $renderList = [];
        foreach ($list as $key => $value) {
            if (is_int($key)) {
                $renderList[] = $value;
            } elseif ($value) {
                $renderList[] = $key;
            }
        }

        return implode(' ', $renderList);
    }
}

Example usage:

// will return "default-class class-a"
$classnames = cn([
    'default-class',
    'class-a' => true,
    'class-b' => false,
]);
svenluijten commented 5 years ago

You can create your own functions.php file an include it in your project via Composer's autoloading files option, I don't think this cn function would fit in the core framework.

godstanis commented 5 years ago

@obaydmir , can you provide a real-life use-case for this feature, please? I'm intrigued :thinking:

upd.: Oh, ok, I thought it's all about PHP classes :smile_cat:

obaydmir commented 5 years ago

@svenluijten I already have, but thanks for the help.

The reason why I think it would help is because I now have to put the logic (if, else...) in my template. It sometimes becomes really verbose. But I also repeat the same pattern.

svenluijten commented 5 years ago

So you blade would look like this?

<div class="{{ cn(['some-class' => $errors->has('field'), 'other-class']) }}">
    ...
</div>

And the some-class class would only be applied when the $errors variable contains errors for field? I don't see what's wrong with this:

<div class="{{ $errors->has('field') ? 'some-class' : '' }} other-class">
    ...
</div>

It's shorter, reads easier because it's just plain PHP, and there's no extra maintenance cost.

stefanfisk commented 3 years ago

When there’s a bunch of classes that you want to conditionally toggle, something like classnames really helps keeping templates concise compared to if-ing parts of a string. I’ve got a custom helper for this that I use extensively in all my project.

obaydmir commented 3 years ago

@stefanfisk Exactly. I'm using this helper function for those kinds of purposes.