Closed (fixed)
Project:
Drupal core
Version:
8.3.x-dev
Component:
theme system
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
16 Nov 2015 at 21:52 UTC
Updated:
4 Nov 2016 at 05:04 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
littlecodingThe Attribute class already includes the functions: addClass, removeClass, hasClass, setAttribute, removeAttribute.
Using this: /themes/my-theme/templates/html.html.twig
the body element is rendered something like:
<body class="top toolbar-tray-open toolbar-fixed toolbar-horizontal" data-test="foobar">So is this a case for documentation?
Comment #3
star-szrattributes in that case is already an Attribute object, attributes, content_attributes, and title_attributes are special cased inside \Drupal\Core\Theme\ThemeManager::render() - see related issue. Elsewhere you should be able to find where html_attributes is turned into an Attribute object in preprocess.
You might want to test instead by creating an attribute array entirely in a template or you can create an array of attributes in a preprocess function. Either way, take that variable and then try to manipulate that in Twig (or even just print it), it won't work because it's not an Attribute object.
Hope that makes sense :)
Comment #5
nicholasthompsonI agree that this would be useful.
Use case:
You have a field with many items, say images, and you're making a bootstrap carousel from them. You may want to define a default attributes object for each item that you can easily addClass for the "active" one to.
Comment #6
joelpittet@nicholasThompson any chance you'd like to take a stab at creating this as a proof of concept?
Comment #7
nicholasthompsonI'd love to if I had the faintest idea of where to start... ;-)
Comment #8
joelpittetStart by adding a function or filter in the TwigExtension class.
/core/lib/Drupal/Core/Template/TwigExtension.phpMy guess would be a function that would create a new instance of an Attribute object.
That would likely be all that is need I guess.
Comment #9
mparker17#2571561: Add Twig filter for date formatting, #2398331: Add the ability to attach asset libraries directly from a template file, and #2308187: Provide a twig extension for file_create_url do something similar.
Comment #10
hctomI'd totally appreciate this in order to be able to include templates with a completely new Attribute() object set in the include-statement. This is for example needed when building templates within the atomic design process, to be able to add modifier classes while including a subcomponent template.
Comment #12
heddn+1 on the idea here. I'm going to mark this as novice, because creating a small helper function in TwigExtension per comment #8 is super simple to do.
Comment #13
ytl commentedI'll try work on this at Drupalcon Dublin
Comment #14
ytl commentedComment #15
heddnThis should match the parameter arguments provided by Attribute.
This doesn't add multiple attributes. Maybe calling this addAttribute would be better.
No type hinting or default values so if someone doesn't pass anything, this is going to fail miserably. Take a look at the default constructor arguments on Attribute and copy/paste them into here.
Comment #16
Charlotte17 commentedCalled an array in a function __construct with a class Attribute
Comment #17
lauriiiThanks for working on this issue! This would be very useful improvement.
I think we should use underscore writing compound since all the other Twig functions are following that pattern
s/Create/Creates
This should include the full namespace
I think this should return new Attributes object even if $attributes is empty
The attributes object should be returned in the end
Comment #18
Charlotte17 commentedThis patch include all items comments into #15 and #17
Comment #19
Charlotte17 commentedComment #21
lauriiiI iterated that a little further
Comment #22
lauriiiHere's interdiff
Comment #23
joelpittetnit: An empty Attribute object that can be cloned.
This outside if is not needed. It should always check attributes
!isset($this->attributes)and if it's not there create the empty new object.After clone if it's ! empty, maybe something like this. (like the constructor but not in the constructor)
foreach ($attributes as $name => $value) {
$cloned_attributes[$name] = $value;
}
If that's getting to messy we can look at that in a follow-up issue for a slight performance gain.
Comment #24
heddn#23 makes sense. I went a little further and renamed the property from $this->attributes => $this->attribute. Interdiff attached.
Comment #25
heddnSince this is a new feature, also moving to 8.3. Although (hint, hint) this would be awful nice in 8.2 as well.
Comment #26
joelpittetI think this looks very well put together. I'll add this to the twig_extensions if it takes a while to get in.
Comment #27
joelpittetDidn't mean to change the version.
Comment #28
heddn@joelpittet, that seems to just be a wrapper around twig upstream. Maybe opening an issue in twig_tweaks or some other twig++ contrib module is a better fit. And given this is slotted for 8.3, it will be a few months before folks start seeing it generally available.
Comment #29
joelpittetHmm good point, don't want to scope creep my own project, lol. Yeah, I can do something like that too, hopefully in a non-disruptive to when the filter gets into core.
Comment #30
star-szrNice kittens. Can we test adding multiple attributes, please?
Comment #31
Charlotte17 commentedIn this patch add multiple attributes #30
Comment #33
Charlotte17 commentedHere I applied correctly patch #24 and add attributes asked in comment #30
Comment #34
heddnWhitespace.
Let's add some attributes that aren't class, maybe try a data-* attribute. And also, let's leave some empty ones too, just for completeness.
Comment #35
Charlotte17 commentedFixed 2 items to comments #34
1.Whitespace
2. Add some attributes
Comment #37
T'Bell Hernandez commentedfixed
space fixed
added empty div
Comment #38
lauriii#30 is addressed
Comment #39
alexpottWhy the cloning dance?
Comment #40
joelpittet@alexpott it's what we do in core for attributes that get created often for performance instead of re-instantiating the same class.
References:
We can do without it too, it's just to continue the pattern.
Comment #41
joelpittetThere is a missing space here that could be fixed on commit:
'data-value' =>['foo']Or I'll fix it in a re-roll if we are going to remove the performance clone stuff.
Comment #42
alexpottI don't think that that micro-optimisation is worth in a method with only a single test call in core. If it becomes an issue then we could change it. Also I doubt that this test result still holds for PHP7... https://stackoverflow.com/questions/18040137/which-is-more-efficient-whe...
Comment #43
Anonymous (not verified) commentedSorry, but it slower than just "return new Attribute($attributes);" in my test like
In any case, it will not hit performance, in contrast to the simplicity and the beauty in this case.
Comment #44
joelpittetRemoved the micro-optimization, thanks @alexpott. Also fixed the array space, added a description to the test and removed the extra arrays in the attributes that aren't needed(only
classneeds to be an array)Comment #45
joelpittet@vaplas Nice script, what version of PHP were you using and which method was which approach(could you edit your comment)?, I tried it and couldn't get a big diff either way which was closer to what @alexpott mentioned.
Comment #46
Anonymous (not verified) commented@joelpittet, thank you for correctness to me and patch #44. I'm tested it - works well!
Also I know, that my script not nice and looks clumsily. I just wanted to quickly compare "new object" vs "cloning". I tested it with php 7.0.8 on Windows in theme_hook (e.g. hook_preprocess_node). With different order and different arguments. Without warm opcache and other special things. Every case "return new Attribute()" won by time. But i'm not saved the script and closed the editor already. I hope this information is enough and will be able to repeat it, if the desire remains :)
Comment #47
lauriiiLatest patch works and looks good!
Comment #48
alexpottWe also need a CR to tell people about this new functionality.
Comment #49
lauriiiCreated CR
Comment #50
Anonymous (not verified) commentedI know that my next words may irritate after all this work. But my heart will not feel comfortable if I did not ask about it: create_attribute - it is real pretty name? I know that "attributes" exist in Twig. But may be:
or other words "params", "pairs". Although the attributes - the official term HTML.
After fixing this issue the name will forever. If there is a chance to use the most lovely name, we must to use it.
In any case, thank you for the realization of this issue. Templates certainly become better with it.
Comment #51
lauriiiThat is not correct. We can change it later with BC layer in case we feel like changing it.
Comment #52
joelpittetI'm not against the name we chose, the short hand ones are a no go at all, as we try to use full words and not abbreviations in core.
Comment #53
joelpittetAlso this has some sense, it's clear what it's doing. It creates an
Attributeobject, so follows the name and doesn't obfuscate that fact, even though that name singular has thrown me a few times, it makes sense.Comment #54
heddn+1 on create_attribute. It was what I naturally was planning to call this thing when I first looked at this issue.
Comment #55
Anonymous (not verified) commentedOk. Now I look at the "create_attribute" as "new Attribute" and see the sence too. Thanks for your callbacks and your brains :)
Comment #56
star-szrThis should be prefixed with (optional) per https://www.drupal.org/node/1354#param.
Related to this, maybe we should test that calling create_attribute with no arguments still returns an empty attribute object because that would be useful I'd say.
Comment #57
joelpittetThis should work as a test, uses the method on the object without any args added to the create_attribute function.
Comment #58
lauriiiLooks great
Comment #60
star-szrFixed a minor grammar thing on commit, interdiff attached.
Also made some tweaks to and published the change record.
Committed 99a55f0 and pushed to 8.3.x. Thanks!
Comment #61
star-szrOops wrong interdiff (wrong folder). This one.