How to create angular <popover-content> dynamically? - html

I am trying to create some angular dynamically.
Statically created works.
eg.
<div>
<popover-content #pop1
title="Hello"
placement="right"
[closeOnClickOutside]="true">
Popup One
</popover-content>
<popover-content #pop2
title="Hello"
placement="right"
[closeOnClickOutside]="true">
Popup Two
</popover-content>
Testing this <span [popover]="pop1" [popoverOnHover]="true">Pop1</span>.
Testing this <span [popover]="pop2" [popoverOnHover]="true">Pop2</span>.
</div>
Now, I want to create these s dynamically from my data.
But then it doesn't work with this #pop1/#pop2 thing.
Non-working code:
<div>
<popover-content *ngFor="let p of allPops; let index = index"
#pop{{index}}
title="Hello"
placement="right"
[closeOnClickOutside]="true">
{{p.message}}
</popover-content>
Testing this <span [popover]="pop1" [popoverOnHover]="true">Pop1</span>.
Testing this <span [popover]="pop2" [popoverOnHover]="true">Pop2</span>.
</div>
So, this #pop{{index}} doesn't work. I also tried with the following style [attr.id]="'#pop' + index". Doesn't work too. So what's so special about this # inside a custom tag? How can I dynamically create it and make it work?

This is unfortunately not possible, more about this issue here:
https://github.com/angular/angular/issues/4581
Sorry, anchors have to be statically analyzable and hence can not be dynamically generated. Same way as you can not dynamically create local variables in programing languages.
Local references are not suitable for such a thing I am afraid...
Btw local template reference is not the same as id attribute. The thing you tried would work just for assigning the id attribute, prefixed with #.
https://angular.io/guide/template-syntax#ref-vars

Related

How to get a I18n variable value I can return to my Angular parent component?

I'm new to Angular and I just put in place an i18n (2 languages) system for a website I am creating. Everything works properly but in order to switch from one language to another in my header, I feel stuck.
I followed the Angular documentation to transfer my variables from child to parent component and I ended with this:
<input type="text" id="item-input" #lang>
<button type="button" (click)="changeChosenLang(lang.value)">
{{ 'global.lang' | translate }}
</button>
As you can see, I write my language in the input form and I send it to the proper component with a button. What I wanted was to click on my 'global.lang' text and to be able to send its value to the parent component, since the value is the language which is not actually used.
I don't know how to put my 'global.lang' text in a variable, neither what kind of balise I can use. Also I didn't know how to summarize my problem to search for it on StackOverflow so if you know a similar post, don't hesitate to post the link.
Thank you for your reading!
I found a less tortured way (poor brain) to have the result I wanted:
<span (click)="changeChosenLang()">
{{ 'global.lang' | translate }}
</span>
First I temporary changed my button to a span balise and I deleted the parameter from my changeChosenLang() function. Then, I transferred a variable 'lang' from my parent component to this one, witch contains the value of the language chosen in my app constructor. At each click, I change its value in my changeChosenLang() function and everything works great!
I hope it can help someone someday. The moral of this post is: the simpler, the better! Have a good day.

With use PathVariable CSS not loading and how to fill form to update in thymeleaf

I am trying to do same small service and sometimes I am sending requests to my Rest Api.
I am getting two problems:
How to fill field in form in html using thymeleaf? I have form like this and would like to fill fields with current values (th:value="${}" - not working for me):
<form th:action="#{/offences/edit}" method="post" th:object="${createOffenceForm}"> <input th:field="*{name}" th:value="${currentOffence.name}"/> <input th:field="*{penaltyPoints}" th:value="${currentOffence.penaltyPoints}"/> <input th:field="*{amountOfFine}" th:value="${currentOffence.amountOfFine}"/> <button type="submit">UPDATE</button> </form>
The problem is with loading css styles to html when I redirect to the site with path variable. For example i created html with two buttons. First one is hardcoded:
<a th:href="#{/offences/test}" class="link" style="text-decoration: none"><button class="buttonOK" type="submit">EDIT</button></a>
after redirect my site looks like this (everything works, it should be like that):
`
and here is after second button - redirect with path variable:
<a th:href="#{'/offences/edit/' + ${offence.id}}" class="link" style="text-decoration: none"><button class="buttonOK" type="submit">EDIT</button></a>
and view after load:
For the issue with your form data not being filled, this is because th:field and th:value are not meant to be used at the same time. So th:field ends up overwriting you value.
In your case I would suggest either manualy setting name (and id) or replacing th:object with the a filled version of the bean you want to return and only using th:field
As for the second issue it looks like a faulty fragment return on a post call to me but need to atleast have the controller functions and more complete html to say anything about that. And in general it's advisable to have 1 question per problem and not bundle things.
Ok so i found soultion.
To fill fields in form I only had to add to ModelMap form with fields.
Something like this and thymeleaf autofilled fields in html.
modelMap.addAttribute("createOffenceForm", new CreateOffenceForm(offenceDTO.getName(), offenceDTO.getPenaltyPoints(), offenceDTO.getAmountOfFine()));
Second solution is simple too. When changed mapping in Controller from #GetMapping("/path/{id}") to #GetMapping("/path-{id}") - everything works. There is no other problems with styles...

Get the last 2rd item in HTML

I have used Django to develop a webapp
In the admin model, I used Django simple UI package, I want to choose the last 2rd one in the list(models)
How could I slice in the below?
<div v-for="(c,j) in models" :key="c.name" class="quick-wrap">
<a href="javascript:;" #click="openTab(c,(j+1)+'')">
<span class="icon" :class="c.icon"></span>
<span class="card-name" v-text="c.name"></span>
</a>
</div>
Not sure what last 2rd means, but if you want the last 2 items in what appears to be a context variable called models you can do that in the view you use to call this html file. Using a slice on your queryset you should be able to pass models[-2:] to get the last two and pass that instead of models. Vue may have a way to slice as well, but if you can do it in the view, it probably makes sense to do so.

Tooltip not working inside a tag with ngFor attribute

Could someone explain to me why the tooltip in this piece of code using Angular 4 templates doesn't work?
<template ngFor let-channel [ngForOf]="channels">
<td>
<em *ngFor="let color of findBallsColor()" class="fa fa-circle {{ color }}" [tooltip]="id"></em>
</td>
</template>
<ng-template #id>
test
</ng-template>
If I remove the *ngFor inside the <em> tag it works fine (showing just one element obviously). I'm quite new to Angular so probably I'm missing some understanding of how it really works here.
EDIT
I found out the problem comes from the type returned from the Typescript function. In the code above, the list returned by findBallsColor() is actually an object that contains 4 fields. When I change it to just return a string it works. So the code looks similar to this:
HTML:
<template ngFor let-channel [ngForOf]="channels">
<td>
<em *ngFor="let color of findBallsColor()" class="fa fa-circle {{ status.color }}" [tooltip]="id"></em>
</td>
</template>
<ng-template #id>
test
</ng-template>
TS:
findBallsColor():any[] {
return [{"statut":"ERROR","name":"name","otherField":"value","anotherField":"value"}];
}
Does anyone know the why of this behaviour?
I had a similar problem, here's an excerpt from this Github issue, that details what is wrong with the way you get your data for your *ngFor.
Calling a function from the template is not a good practice and this is an example of why this recommendation exists.
When the tooltip is fired in the first case, it starts an angular detection cycle, which in turn calls items() again and it tries to show the tooltip again and it starts another angular detection cycle and it goes on and on and on repeatedly.
At first, the recommendation exists to avoid performance issues, but it has other consequences like in your case.
If you put a console.log in items(), you'll see it keeps being called again and again...
If calling a function is mandatory, use a pipe instead.
So, in your code, if you used a pipe or an observable or array of some sort, then your tooltip would work, but currently it just keeps calling the function.
This worked for me - add data-toggle="tooltip" to the html tag - aka the tooltip.
Then target the tooltip via the body $('body').tooltip({selector: '[data-toggle="tooltip"]'});

Rspec and Watir; locating and changing <span> text within a button element

I am playing around with rpsec and watir-webdriver, and am encountering a strange issue where I can click into a button, but I cannot interact with (or change) the text in the span inside. This is what the html looks like:
<button class="pure-button toggle-mode button-link edit-text-button-element" data-reactid=".0.1.0.1.1.0.0.0.0" title="Edit">
<span class="value false" data-reactid=".0.1.0.1.1.0.0.0.0.0">Untitled</span>
</span>
</button>
Right now my ruby code looks like this:
foo = #browser.button(:class, 'pure-button toggle-mode button-link edit-text-button-element')
foo.click
foo.span.set('Hello')
Running this gives me the initial error expected Hash or (:how, 'what'), got ["Hello"]
Any thoughts on what I'm doing wrong here?
Found a solution that works: after clicking to interact with the element, I was able to set text by using send_keys. So I did this:
foo = #browser.button(:class, 'pure-button toggle-mode button-link edit-text-button-element')
foo.click
#browser.send_keys {keystrokes simulated here}
That is because you cannot set text of the span in watir-webdriver. At least so easily. But if you will do for example:
puts foo.span.text
it will work. Here is the full list of what you can do with span: Usefull Link
Of course there is the way to change the text in your span:
browser.execute_script("arguments[0].textContent= 'Hello'", foo.span)
But I cannot imagine the situation when it will be really necessary for the real testing in a real world.
The class locator only accepts a single class.
If you need all of the classes for it to be unique do:
#browser.button(css: ".pure-button.toggle-mode.button-link.edit-text-button-element")