Directive with Replace=false creates list html that is non semantic

46 views
Skip to first unread message

Kenese Lautusi

unread,
Jan 17, 2016, 8:19:32 PM1/17/16
to AngularJS
Hello all,

We are thinking about moving to directives that use replace=false, as I hear replace=true is being deprecated. One problem I cant figure out how to fix is for all directives that are based on lists, the resultant html is not semantic.
 
For example a list directive might be something like:

<tg-list tg-compact="true">
<tg-list-item>foo</tg-list-item>
<tg-list-item>bar</tg-list-item>
</tg-list>

this will currently (with replace=true) compile to:

<ul class="o-list o-list--compact">
<li class="o-list-item">
        foo
</li>
<li class="o-list-item">
        bar
</li>
</ul>


with replace=false we will end up with either:
<tg-list class="o-list-icon o-list-icon--compact">
<ul>
<tg-list-item>
<li class="o-list-item">foo</li>
        </tg-list-item>
<tg-list-item>
<li class="o-list-item">bar</li>
        </tg-list-item>
</ul>
</tg-list>
or:
<tg-list class="o-list-icon o-list-icon--compact">
<tg-list-item>foo</tg-list-item>
<tg-list-item>bar</tg-list-item>
</tg-list>

the first is bad because it is definitely non semantic, the second is bad because although it is "semantic" (as in html5, custom tags are ok), we lose anything that ul>li would have given us (a screen reader for example may have special ways to treats them).

Perhaps we can use html5 role attributes? But if so i think the list item would need add the role to the element in the link function?

The ideal solution would be the compiled html that uses ul/li semantically, otherwise an indication of how to get roles working if that will do the job

Dunno, but how have you lot solved this?

Cheers!

Sander Elias

unread,
Jan 18, 2016, 8:17:50 AM1/18/16
to AngularJS

Hi Kenese,

You can use a attribute selector in stead of a tag selector for your directive.

  <ul>
     <li tg-list-item>...</li>
     <li tg-list-item>...</li>
   </ul>

Regards
Sander

Kenese Lautusi

unread,
Jan 19, 2016, 12:07:18 PM1/19/16
to ang...@googlegroups.com

Thanks for the response. I was trying to avoid that as we have a large component library, where we use element directives for all of the components. We don't really want the consumers of the components to have to remember specifically lists need to use the attribute syntax

> --
> You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/rq94vFZagNs/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
> To post to this group, send email to ang...@googlegroups.com.
> Visit this group at https://groups.google.com/group/angular.
> For more options, visit https://groups.google.com/d/optout.

Sander Elias

unread,
Jan 19, 2016, 12:18:03 PM1/19/16
to AngularJS
Hi Kenese,

As an alternative you can build your own replace directive. There are some mayor pitfalls with it tough. (the core reason it's deprecated to begin with). If you know your code and use cases, it can be worked around. Not an easy task tough.  Part of the problem is, that the dom nodes you remove are holding the angular references you want to keep (this is put a bit simpler as it is..)

Regards
Sander

Kenese Lautusi

unread,
Jan 19, 2016, 11:00:02 PM1/19/16
to AngularJS
Great, thanks for your reply. I guess i'll see if role attributes will do the job, as my own replace directive sounds like the sort of thing i could really screw up :)

--

Kenese Lautusi

unread,
Jan 20, 2016, 11:51:34 PM1/20/16
to AngularJS
Hi Sander,

For now im just going add a line in the tg-list link that wraps the each of the tg-list-item's before they are compiled:

public link = ($scope: angular.IScope, $element: angular.IAugmentedJQuery) => {
$element.find('tg-list-item').wrap('<li></li>');
}
   
It is doing the job i want (ul > li > tg-list-item), and i don't think i will have slowed things down too much (i was trying to avoid compiling myself for that reason) but do you think this is a bad idea for any reason? If not it is what ill stick with.

Thanks for your help!
Kenese

Kenese Lautusi

unread,
Jan 21, 2016, 12:04:16 AM1/21/16
to AngularJS

My guess is this might not work with tg-list-item in a repeater actually. Doh. Haven't tried yet tho, will do in the morn


--

Sander Elias

unread,
Jan 21, 2016, 3:13:15 AM1/21/16
to AngularJS
Hi Kenese,

This should work, even in a repeater. I'm not sure if wrap will cause a new $compile. If it does that, it's an 'expensive' operation. 

Regards
Sander

Kenese Lautusi

unread,
Jan 21, 2016, 6:22:24 AM1/21/16
to ang...@googlegroups.com

Great, thanks again


--

Kenese Lautusi

unread,
Jan 21, 2016, 5:32:58 PM1/21/16
to AngularJS
This didnt quite work as repeaters hadn't been run in the list link, but something similar did:

The list-item link:

public link = ($scope: angular.IScope, $element: angular.IAugmentedJQuery) => {
    $element.wrap('<li></li>');
}

So each list-item deals with wrapping itself. 

Thanks for your help Sander
Reply all
Reply to author
Forward
0 new messages