List of directives and transclusion - angularjs

I'm trying to build some navigation directives to isolate complexity. I want the following HTML to render my navigation:
<custom-nav>
<nav-item>Item 1</nav-item>
<nav-item>Item 2</nav-item>
<nav-item>Item 3</nav-item>
</custom-nav>
If I wrote the directives right now, the resulting compiled HTML would look like this:
<custom-nav>
<nav>
<ul>
<nav-item><li><a>Item 1</a></li></nav-item>
<nav-item><li><a>Item 2</a></li></nav-item>
<nav-item><li><a>Item 3</a></li></nav-item>
</ul>
</nav>
</custom-nav>
however, this is invalid HTML (<ul>s can only have <li>s as children).
Without using replace: true, what is the best way for me to tackle this? The only things I can think of are:
Don't use <ul> or <li> - use aria roles to define my own list items.
Don't make the list semantically a list. I really don't want to do this.
Is there something I'm overlooking?

I am not sure if I understood the issue correctly, but what I can say is,
you can pass the items you want to use as li, in an array, as a parameter to the directive, and loop over it in your link function to generate the recommended html result, that would remove any complexity related to the issue
please let me know if I misunderstood you.
Best of luck

Related

How can my template include an element whose type is determined by an expression in angularjs?

It's 2022 and sadly I'm learning AngularJS (already past end of life!)
I need need to use what might be called a dynamic element/component. Pseudocode example:
In controller:
this.theElementName = 'b';
In the template:
<{{$ctrl.theElementName}}>this is some text</{{$ctrl.theElementName}}>
I would want this to create <b>this is some text</b>.
The reason is that I want to generate an array of different directives to render, and I don't want code like:
<b ng-if="$ctrl.theElementName === 'b'">this is some text</b>
<div ng-if="$ctrl.theElementName === 'div'">this is some text</div>
<directive-abc ng-if="$ctrl.theElementName === 'directive-abc'">this is some text</directive-abc>
...
In Svelte, it's
<svelte:element this={theElementName} />
In Vue it's
<div :is="theElementName" />
EDIT: in response to the reluctant 'that person', clarifying the use-case
Consider a user-configurable UI. The result of the configuration might be an array list of components desired. I would then need to loop and output those different components in my template. Of course the components would need a standard interface for properties passesd in, events emitted etc. but that can all be designed for.
My code could do a big switch statement, but that requires prior knowledge of every possible component that might be used now or in the future. By doing it the way I intend to, however, a future person could add a component without needing to touch this code.
You can write directive my-directive to use:
<div my-directive="$ctrl.theElementName">...
to generate:
<div><component-a>...
<div><component-b>...
<div><component-c>...
All directive should do is to generate html string and compile it:
element.append($compile('<' + scope.myDirective + '>...')(scope))
(also remember to update content in onChanges if you want to support it)
Directive may also copy certain/all attributes from original element etc.
P.S. you should be cautious e.g. if component name comes from database that may allow injections.
Not a brilliant solution, but documenting what is more of a workaround.
ng-include can be used to source another template file. That file can contain the component you need to include.
<ng-include src="'/path/to/' + theElementName + '.html'"></ng-include>

ISML conditional CSS class declaration

I'm new to SFCC and I was wondering what is the best practices with writing conditional CSS classes in the ISML template. I couldn't find anything in the documentation specifically for element parameters but I have seen some code which works but doesn't look right to me.
<div class="foo <isif condition="${bar}">baz</isif>"></div>
Is this the right way to conditionally add a CSS class?
This is the documentation I've found for isif
https://documentation.b2c.commercecloud.salesforce.com/DOC1/index.jsp?topic=%2Fcom.demandware.dochelp%2FScriptProgramming%2FDemandwareJavaScriptExpressionsinISML.html
This variant is a little bit shorter
<div class="foo ${bar ? 'baz' : 'someting else'}></div>
From my understanding you first need to write the isml condition and inside it the html div, something like this:
<isif condition="${bar}">
<div class="foo">baz</div>
</isif>">
I'm only a couple months new to SFF so forgive me if I'm wrong.

Show which directives is being used in a page

is there a way to show wich directives is being used in a page ?
Please, take a look at this example
<div>
some things ...
<mydirective></mydirective>
<mydirective1></mydirective1>
<mydirective2></mydirective2>
some things ...
</div>
And this is the "mydirective" html
<div>
<mychilddirective></mychilddirective>
<mychilddirective1></mychilddirective1>
<mychilddirective2></mychilddirective2>
</div>
Question 1: So, my point is, how can I show the list of directives used (like in console log or somewhere else) in this page ?
The answer for this question should be
mydirective, mychilddirective, mychilddirective1,
mychilddirective2, mydirective1, mydirective2
Question 2: If there is a answer for question 1, is there a way to "discover" the used directives using the browser console ? Or I need that my directives have to be following some kind of pattern ? (like some attribute or something like that ...)
Every directive has link functions. That are called in a sequence. You can use them to identify which directive is being used.
Here are links for more detail about link function and their calling sequence.
https://www.undefinednull.com/2014/07/07/practical-guide-to-prelink-postlink-and-controller-methods-of-angular-directives/

ng-click not working inside ng-switch

I'm beginner with AngularJs, and i have a lot of questions :/
Here's one of them :
I have links that i use to filter data. So when i click on link one, the value for the filter myFilter is one, etc.
Just to show you that my filters work, i putted two times the links (see here http://plnkr.co/edit/2G6mahkmyIixMJ1mEVKp?p=preview)
In the above links, i use ng-swich, cause i want, when i click on a link, to remove the link and only keep the text
In the bottom links, there are no ng-swich, so myFilter works perfectly
Is it possible, to make the ng-click inside the ng-swich work ?
The way you are approaching the issue involves far too much code duplication.
Also it is a bad practice to replace objects directly in the html. If you use a function bound to the scope it is cleaner and you won't run into child scope issues as much
Rather than creating four <ul> you could simply use ng-if within each <li> and use only one <ul>. This would also be a good case to create a very simple directive
HTML
<li>
<span ng-if="myFilter.trimestre==1">Avril - juin</span>
<a ng-if="myFilter.trimestre!=1" ng-click="updateFilter('trimestre',1)" href="#">Avril - juin</a>
</li>
JS
$scope.myFilter={};
$scope.updateFilter = function(key, val){
$scope.myFilter[key]=val;
}
DEMO

Show directive as result of a click

I want to show content that comes from a directive when the user clicks on a link.
<li>Show popup</li>
Obviously I'm new to angularjs. I know the approach above doesn't make sense really but I was also trying to imagine how this might be done with ng-if but not coming up with anything. Any ideas? Thanks!
Edit 1: The directive that I want to use is:
<ng-pop-up></ng-pop-up>
That's part of ngPopup.
Edit 2: This is now resolved. It turns out that in the case of ngPopup, you put the directive somewhere, then you open the dialog using the open method, so I really didn't take advantage of the solutions given here. Giving Martin credit because his solution solves problem originally stated. Thanks all.
Not exactly sure what you are looking for.
When you say, content from a directive, is this an existing directive, or do you think the content should come from a directive?
In your example where you have show popup, do you mean you would like to have a dialog displayed when you click the link?
Or do you just want something like the following example?
angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app=app>
<a href="#" ng-click='showMessage = true'>Click Here</a>
<div ng-show="showMessage">Your Message Here</div>
</div>
Try looking at using ng-if (AngularJS docs). You can use a boolean in your scope to that is toggled by the ng-click.

Resources