Angular 2+ using jQuery's append alternative in app.component.ts method - javascript

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)

Related

Conditinally rendering text using Angular clipboard

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.

How can a template-driven form access a control inside a component?

I have a <form> that uses the Template Driven approach.
The form contains a mix of native controls, like <input> and <select>, and also wrapper components, like <text-control> and <checkbox-control> that contains the native <input> element inside of it.
How can the form access the <text-control>'s native element to read its error and touched state?
Also, if I want to place a validator directive on that wrapper component and have it pipe-down to the native <input>, how can I approach this?
I tried to use ngModel on the wrapper component, but it doesn't work, since ngModel is hooking to the wrapper component, not the underlying <input> element.
Another approach was to use <ng-content>, but the underlying native element takes a lot of attributes, so much that it'll be a pain to copy-n-paste it everywhere.
Example:
<checkbox-control>
<!-- Now, it's easy for the form to access the control. -->
<!-- But I've too many attributes and properties that go here. -->
<input type="checkbox">
</checkbox-control>
PS: I am not looking to use ElementRef to access the native element, I just want the <form> to be aware of the native elements' error state, so that I can tell whether the form is valid or not.
Example:
<form #editor="ngForm">
<input type="text" validateText />
<select validateSelect>
<option value="1"></option>
<option value="2"></option>
</select>
<!-- Does not work. -->
<checkbox-control validateCheckbox></checkbox-control>
</form>
Thanks in advance.
You can use element's local reference in template approach.
Please refer to this code I just wrote to explain :
https://stackblitz.com/edit/angular-ivy-7no9ok?file=src/app/app.component.html
I found a reasonable solution that works without writing much code, and without editing too many components.
Step 1: Create your validator
#Directive({ selector: '[assertNoSpecialChars]' })
export class SpecialCharacterValidator implements Validator {
// The directive will have a reference for the name of the form's control.
#Input() assertNoSpecialChars: string = '';
validate(group: FormGroup): ValidationErrors | null {
const control = group.controls[this.assertNoSpecialChars];
// For simplicity, let's say we don't want the dollar sign in our input.
if (control.value.includes('$')) {
return { invalid: true };
} else {
return null;
}
}
}
Step 2: Apply the directive on your form
<form #f="ngForm" [assertNoSpecialChars]="'username'">
<text-control></text-control>
</form>
Step 3: Bind the input event of your component to the hosting form component
<form #f="ngForm" [assertNoSpecialChars]="'username'">
<text-control (input)="updateFormManually($event, 'username')"></text-control>
</form>
Step 4: Get a reference for your NgForm, and implement the update mechanism
#Component({})
export class FormComponent implements AfterViewInit {
// Grab a reference for your NgForm.
#ViewChild('f', { static: true }) f!: NgForm;
// Create your form control.
username: FormControl = new FormControl();
// Register your control to the NgForm.
ngAfterViewInit(): void {
this.f.form.addControl('username', this.username);
}
// Update the control manually.
updateFormManually(event: any, controlName: string): void {
this.f.form.controls[controlName].setValue(event.target.value);
}
}
Now, the form's validity state, and error messages will be correctly bound.

(Angular) How can I get the #tag definition in html to Javascript?

I am having difficulty working on an Angular project.
In HTML...
<input #abc>...</input>
In Javascript
let var = ... *(how can i get the input element 'abc' to javascript?)*
I know it's too basic,
I am having a lot of trouble. Help!
this a template reference, you need to grab this element using #ViewChild decorator
#Component({
template:" <input #abc>...</input> "
})
export class SomeComponent implements AfterViewInin{
#ViewChild("abc")
element:ElementRef<HtmlElement>;
ngAfterViewInit(){
console.log(this.element.nativeElement);
}
}
I encourage you to read, the following topics to get the knowledge for that
https://angular.io/guide/component-interaction#parent-calls-an-viewchild for viewChild
https://angular.io/guide/template-syntax#template-syntax for template reference
you can refererence it with a
#VhiewChild('abc') myInput: ElementRef;.
however if you want JUST value more valid and easy way to make a field on you class, lets say value
and update it when your input updates <input (input)="value = $event.target.value" [value]="value">
if you use event
<input #abc (click)="getabc(abc)">...</input>
getabc(element) { console.log(abc) } //element input
if just get in .ts
#ViewChild("abc") element:ElementRef<HtmlElement>;
you can get element .

How to force Angular 2 [(ngModel)] change after changing input value with Javascript?

I am trying to replace Japanese half-width characters to full-width characters.
ウ -> ウ
So whenever a user types in half width, we have to convert to full width automatically.
Obvious solution would be to design a directive to change the ngModel on keypress. But we have a huge codebase and I was thinking maybe with #Hostlistener would be able to change the value.
#HostListener('document:keyup', ['$event']) onKeydownHandler(event) {
if (event.target.hasAttribute('type')
&& event.target.attributes['type'].value === 'text') {
event.target.value = this.changeToFullWidth(event, event.target.value);
}
}
However with this [(ngModel)] is always one character behind and I know this is because I am touching the HTML element directly.
Is there a way to do this ? Or will I have to go harder approach of adding directive to each input tag in whole project?
At last I was able to trigger model change following way:
targetElement.dispatchEvent(new Event('input'), {bubbles: true});
But found out that it doesn't work in Edge for CKEditor.
For that we can use the directive and model service
...
constructor(
...
private model:NgModel,
...
){
...
onInputChange($event){
...
this.model.valueAccessor.writeValue(this.changeText(modelValue));
...
}

ngIf and click not working for dynamic html in angular2

ngIf and click not working for dynamic html.
when load html using innerHtml then ngIf and click event not loading.
export class FillInBlanksComponent implements OnDestroy, OnInit {
question = '';
editable = true;
ngOnInit() {
question = '<span *ngIf="editable" name="answers['+incr+']" contenteditable="true" (click)="onclick()"> </span>';
}
onClick(){
alert("clicked!!!!");
}
}
The function you're calling is (click)="onclick()" but you've defined onClick().
Another thing is, you might want to DOM Sanitize the string else you'll get a warning. Please check this answer out on how to do that.
check you have done spelling mistake use (click)="onClick()"
you are using small c in your function call

Categories

Resources