I want to implement a simple copy-to-clipboard function in my Angular application.
The function to copy works, however, I do not understand how conditional statements in Angular as most of my experience is in React.
In React I would define my variable
[copy, setCopy] = useState(false)
Then, I would pass this into wherever I want to change the text or graphic element:
<button>{copy ? "click to copy" : "url copied"}</button>
Using the Angular docs, this is what my copy function looks like in Angular:
export class ThankyouComponent {
copied = false
value ='https://url.com'
}
And here is where I want to use it in my HTML file
<button [cdkCopyToClipboard]="value">{{SOME_EVENT ? "copy url" : "url copied" }}</button>
How do I access the click event of cdkCopyToClipboard in order to conditionally render the string within the button as in my React example? I've been looking around online and can't find a solution.
to display something conditionally inside an HTML template in Angular, you can use property that holds text
In HTML button attribute you can add
(click)="myOnClickMethod()"
Which calls method inside ts file whenever click event occures.
And in that method (that should belong to ts file in the same component you can do something like which changes button text to anything you want after the click.
#Component({
// Omitted for simplicity
})
export class MyComponent{
public buttonText: string = 'Copy url'
public myOnClickMethod(): void {
this.buttonText = 'Copied'
}
}
Then you can pass that variable with string interpolation to that button content like
<button ...>{{ buttonText }}</button>
Bonus
If you want to display some blocks conditionally, like some kind of fallback in case of no data, for example, in React you would probably do something like
if(!props.myList || props.myList.length < 1) return <strong>No data</strong>
return <> // some processing </>
In Angular you can use *ngIf directive
<div *ngIf="myList?.length > 0 else no-data">
// some processing
</div>
<ng-template #no-data>
<strong>No data</strong>
</ng-template>
Of course you don´t need to use else statement and you can use opposite condition in other *ngIf instead.
Related
I have been trying to change the underline color decoration of some text according to a specific value given to a React component via this method:
<span className={`underline underline-offset-4 decoration-4 decoration-${decorationColor ? decorationColor : 'primary'}`}> {sentence.text}</span>
However, it is not working correctly. When I inspect the HTML file it has indeed the color I wrote, for instance: decoration-secondary. Nevertheless, the text doesn't appear to be changing accordingly.
If I write directly 'decoration-secondary' instead of passing 'secondary' within the props and then using decoration-${decorationColor ? decorationColor : 'primary'}, it suddenly works.
I found out that this only happens whenever I had not previously directly written the class name within the file. For example: I have used 'bg-primary', 'bg-secondary', and several times in other parts of the app, and thus, when using `bg-${decorationColor ? decorationColor : 'primary'}' it just works perfectly.
TailwindCSS doesn't allow you to generate classes dynamically. So when you use the following to generate the class…
`underline underline-offset-4 decoration-4 decoration-${decorationColor ? decorationColor : 'primary'}
…TailwindCSS will not pick that up as a valid TailwindCSS class and therefore will not produce the necessary CSS.
Instead, you must include the full name of the class in your source code. You can return the full value like this
function myDecoStyle(decorationColor) {
if(decorationColor)
return "underline underline-offset-4 decoration-4 decoration-"+decorationColor;
else
return "underline underline-offset-4 decoration-4 decoration-primary";
}
where decorationColor is your colour value you are passing here.
By doing it this way, the entire string for every class is in your source code, so TailwindCSS will know to generate the applicable CSS.
And use it like
<span className={`${myDecoStyle(secondary)}`}> {sentence.text}</span>
Read more: https://tailwindcss.com/docs/content-configuration#class-detection-in-depth
I am using Lit 2.3 and try to use the the #vaadin/vaadin-dialog component from within my own Lit component to show an input field and access the value of it when a user clicks the Okay button. My own render method looks something like this:
render() {
return html`
<vaadin-dialog
header-title="settings"
.opened="${this.dialogOpened}"
#opened-changed="${this.dialog_opened_change}"
${dialogRenderer(this.renderDialog, [])}
${dialogFooterRenderer(this.renderFooter, [])}
></vaadin-dialog>
`
}
And the renderDialog method that renders the inside of the dialog looks like this:
private renderDialog = () => html`
<div>
<div class="settings-dialog">
<label for="userid">User-Id</label><input name="userid" id="userid" type="text" value=${this.userid}>
</div>
</div>
`
I can successfully open and close the dialog. What I don't understand is how to get the value of the input field after the dialog closed. And in fact I would also like to initialize the value of the input field without using a local state (${this.dockid}), but that at least works.
I tried accessing the values from within "this.dialog_opened_change" but I don't seem to understand what to hang my querySelector on to get to my <input>.
This is what I do, currently, but it looks unorthodox at best to me:
I call the method _apply_settings from a button within the dialog's footer
private renderFooter = () => html`
<button class="modal-ok" id="apply_settings" #click="${this._apply_settings}">
</button>
`
And in the _apply_settings I poke around in the DOM to get to the vaadin-dialog's overlay and use that as a starting point for querySelector:
private _apply_settings(e: Event) {
let overlay = (<HTMLElement>e.target)?.parentNode?.parentNode
let settings = new Settings()
settings.user_id = (<HTMLInputElement>overlay?.querySelector("#userid")).value
this._close_settings()
}
While this works for now, I have trouble believing that it is the way it should be. The documentation unfortunately stops at showing a dialog and never explains how to access things so I wonder if I am missing something entirely trivial?
I want to pass the props (string) value in my scss file
my component uses the nbColor props which is 'warning' and I want to put this value in my scss file which has the class .colorNb {color: color (nbColor);}
I would like nbColor to take the value nbColor = color: color (warning)
My component call <Table :nbColor="'warning'" />
in my component Table <span: class = "{colorNb: nbColor}"> {{nb}} </span>
props nbColor: { type: String, required: false }
It's a bit unclear what you're looking to do, since you're saying you want to pass the value into the scss file but from the example it seems like you're wanting to pass it to a tag as a class.
If you're trying to pass it to the scss file, that's not possible.
The file is compiled, so the value would need to be created at compile time. But there are ways to get around that by using css variables or style.
If you're looking to pass a variable to the class, then you should be able to to achieve that this way:
<span :class="nbColor"> {{nb}} </span>
The following code uses object-based assignment, which uses the key as the value, and the value as a boolean to determine if the value is added or not, so would give you a <span class="colorNb"> if nbColor is set and <span class=""> if it is not. This is usefull for having state-based classes like {active:item.isActive, disabled:item.isDisabled}.
<span :class = "{colorNb: nbColor}"> {{nb}} </span>
I am using angular 7 and I have a textarea on my app.component.html file.
I have given it an id to ta.
On my app.component.ts I have a method and I want to append a string into my textarea.
So I have this:
// app.component.html
<textarea id="ta"></textarea>
// app.component.ts
mymethod() {
// $('#ta').append("this text was appended");
// But I need to do the above without jQuery
}
How can I do this?
You are thinking in jQuery, while you should think in angular. Think of the textarea as a variable. When someone updates the textarea, the variable updates as well, and backwards - if the variable updates, the textarea too.
You can use ngModel to bind a variable to an input or a textarea. Then, append the string to the variable, and it will update the textarea.
// app.component.html
<textarea id="ta" [(ngModel)]="textareaValue"></textarea>
// app.component.ts
public textareaValue: string;
mymethod() {
this.textareaValue = "this text was appended";
}
Don't forget to include the FormsModule in the app module (here you can see how)
I have component in angular
in component.ts i have line of code that serach html element
var myArticle = document.querySelector('article');
this return null
in component.html
<article id="bodyArticle" *ngIf="isClicked"></article>
but when I use article in sibling component.ts
var myArticle != null from component.ts
How it's work querySelector serach element in all file project ?
I also have other problem. In same componen.html i have button
<div class="btnGrp">
<button (click)="loadXML($event)">Load</button>
<input type="file" name="img" multiple (change)="onChange($event)">
</div>
<article id="bodyArticle" *ngIf="isClicked"></article>
When i click button one click emitted is value true firstly and i must click second to button to load thata to article content
snippet from component.ts
loadXML(event?: Event) {
var myArticle = document.querySelector('article');
console.log(myArticle);
if(this.imageService.getBodyRes() == ''){
myArticle.textContent = 'Error can't load data';
this.isClicked = true;
this.xmlLoadedEvent.emit(this.isClicked);
} else {
myArticle.textContent = this.imageService.getBodyRes();
console.log(myArticle.textContent);
this.isClicked = true;
this.xmlLoadedEvent.emit(this.isClicked);
}
}
How to do that when i click button in article tag ngIf set true value and also loadData without dobule click.
Try to avoid using the document object and its methods in Angular. It will make your life very difficult if you try to do that.
<article #articleId id="bodyArticle" *ngIf="isClicked"></article>
You can put a template variable name on the article tag, and then query it with angular's 'ViewChild' class like so -
import { Component, ViewChild, ElementRef, ...others?....} from '#angular/core'
export class MyComponent {
articleToggle: boolean = false; // add a toggle in your component for turning the article on
#ViewChild('articleId') article: ElementRef;
ngAfterViewInit() {
this.article.nativeElement.<<access DOM attributes here>>
}
}
This will give you access to the DOM node, like you expected your document query to have done, but even so, there are probably still better ways to do what you are doing, especially since you mentioned you are trying to use the article in sibling components. If that is the case, you may want to make it its own component allowing you to avoid queries altogether, but again, impossible to know with so little info.
Also, its generally recommended to avoid comparing to null entirely in typescript. Use 'undefined' instead.
<button (click)="loadXML($event); articleToggle = true">Load</button>
Set your variable to true on click, and then for the article.
<article #articleId id="bodyArticle" *ngIf="articleToggle"></article>
Now it will appear after the first click of the button, as that will be the only time the value changes from false -> true.