0

Say I have the following tag:

library(htmltools)

t = div(name = 'oldname')

I can overwrite the 'name' attribute of this tag using t$attribs$name = 'newname' but prefer using htmltools getters/setters, does the package have a function that facilitates this?

Looking through the package manual, the only function that allows for the manipulation of tag attributes is tagAppendAttributes, which only appends the new atrribute value to the original:

t = tagAppendAttributes(t, name = 'newname')
t
#<div name="oldname newname"></div>

Does the absence of a helper function that overwrites the value of an attribute mean that tag attributes are not meant to be overwritten?

user51462
  • 1,658
  • 2
  • 13
  • 41

1 Answers1

0

You're probably overthinking this. Look at the code for tagAppendAttributes:

tagAppendAttributes
#> function (tag, ...) 
#> {
#>     tag$attribs <- c(tag$attribs, list(...))
#>     tag
#> }

All it does is take whatever you pass and write directly to tag$attribs. If you unclass your object you'll see it's just a list really:

unclass(t)
#> $name
#> [1] "div"
#>
#> $attribs
#> $attribs$name
#> [1] "oldname"
#> 
#> 
#> $children
#> list()

I can see why writing directly to an object's data member rather than using a setter might not feel right if you come from an object-oriented programming background, but this is clearly a "public" data member in an informal S3 class. Setting it directly is no more likely to break it that any other implementation.

If you really want to I suppose you could define a setter:

tagSetAttributes <- function(tag, ...) {tag$attribs <- list(...); tag}
tagSetAttributes(t, name = "new name")
#> <div name="new name"></div>
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thanks Allan. My main concern with manually subsetting the tag in this way (`t$attribs`) is that it may no longer work if the tag structure (i.e. a list with components `name`, `attribs` and `children`) is changed in the future, however remote the chance of that happening may be. Check out [this discussion](https://groups.google.com/d/msg/shiny-discuss/6j87S7nuhQA/uZxEQHTICFEJ). Using something like `tagAppendAttributes` just seems like a safer approach. I was also wondering if there was a reason as to why there isn't a setter function for attributes. – user51462 Jun 25 '20 at 13:20
  • @user51462 there doesn't seem to be a direct way to do this in the API, but it seems very unlikely that the authors will change the structure of the objects now. In any case, it is still possible to write a setter function that doesn't directly access the underlying list: just write a setter that takes the tag and the attribute to be rewritten, and returns a new node of the same type with the attributes and children of the old tag copied over minus the new one, which is overwritten. This can all be done with the provided setters and the `tag` function. – Allan Cameron Jun 25 '20 at 13:43
  • That would be a great solution but I'm not sure if the setters provided in the package allow for that. Would it please be possible to provide an example? – user51462 Jun 25 '20 at 22:29