Property 'nativeElement' does not exist on type 'IonContent' - html

I am creating an image zoomIn/ZoomOut in ionic 5, hence the above error.
Below is my script:
HTML
<img #zoomedImage [src]="media.image" />
TS
#ViewChild('zoomedImage', { static: false }) zoomedImage: IonContent;
zoom = 1;
zoomIn() {
this.zoom += 0.1;
this.zoomedImage.nativeElement.style.transform = `scale(${this.zoom})`;
}
zoomOut() {
if (this.zoom > 1) {
this.zoom -= 0.1;
this.zoomedImage.nativeElement.style.transform = `scale(${this.zoom})`;
}
}

Because your using the wrong type in the viewChild. Use:
#ViewChild('zoomedImage', { static: false }) zoomedImage: ElementRef;

Related

Syncfusion NumericTextbox disable select

I am using an Angular NumericTextbox from Syncfusion in my application. We ran in the issue that when you click on the input it will automaticly select it. Is there a way to disable it?
Issue:
https://gyazo.com/a72bd4aaf4ebda7a98256d31e3959a48
Docs:
https://ej2.syncfusion.com/angular/documentation/numerictextbox/getting-started/
HTML:
<ejs-numerictextbox
[floatLabelType]="floatLabelType"
[enabled]="enabled"
[min]="min"
[max]="max"
[placeholder]="caption"
[format]="format"
[ngClass]="{
'e-success': (control?.dirty || control?.touched) && !control?.invalid,
'e-error': (control?.dirty || control?.touched) && control?.invalid,
'hum-show-required': !this.hideRequired,
'hum-required': isRequired()
}"
[currency]="currency"
(change)="updateControlValue($event)"
(blur)="handleBlur($event)"
></ejs-numerictextbox>
TS
export class FormNumberComponent extends FormBaseComponent {
#ViewChild(NumericTextBoxComponent, { static: true }) valueAccessor: ControlValueAccessor;
#Input() format: string = 'n0';
#Input() min = 0;
#Input() max: number;
#Input() currency = 'EUR';
private busy: boolean;
constructor(injector: Injector, stateService: StateService) {
super(injector);
this.initLogging(false, 'FormNumberComponent');
this.currency = stateService.getCurrency();
}
updateControlValue(event: any): void {
console.log(event);
setTimeout(() => {
// todo - hacky way to fix the issue (integration of ejs with form needs to be refactored)
const formControl: NumericTextBoxComponent = this.valueAccessor as NumericTextBoxComponent;
if (!isObjectEmpty(formControl) && !formControl.isDestroyed) {
this.busy = true;
formControl.focusIn();
formControl.focusOut();
this.busy = false;
}
});
}
handleBlur(e) {
if (!this.busy) {
super.handleBlur(e);
}
}
}
Your requirement to disable the auto select functionality of the Numeric textbox inputs can be achieved by using the click event. please check the code below,
Code snippet
<ejs-numerictextbox
value="10"
(click)="OnClick($event)">
</ejs-numerictextbox>
OnClick(args): void {
var position = args.srcElement.selectionEnd;
args.srcElement.selectionStart = args.srcElement.selectionEnd = position;
}
Sample: https://stackblitz.com/edit/angular-vgqmzs-i93zpr?file=app.component.ts

Angular directive *ngIf not working as intended

I have this block of html in my template to show or hide the div.
<div *ngIf="csvVisible">
<p>Paragraph works</p>
</div>
This is my component.
export class SettingsComponent implements OnInit {
csvVisible: boolean = false;
private dataSource: string[];
#ViewChild(MatTable, { static: true }) table: MatTable<any>;
constructor(private dialog: MatDialog, private templateParserService: TemplateParserService) { }
ngOnInit() {
this.templateParserService.subscribe({
next(result: string[]) {
if (result !== null) {
this.dataSource = result;
if (this.dataSource && this.dataSource.length) {
this.csvVisible = true;
} else {
this.csvVisible = false;
}
}
},
error(error: Error) {
console.log(error.message);
}
});
}
Eventhough the DIV is hidden at start, it doesnt automatically show / hide on the csvVisible value change. Value of csvVisible is properly set when the observer emits data. [hidden]="csvVisible" isn't working either.
Edit :
Subscriber registration on the service is done by the following code.
private subject = new Subject<string[]>();
public subscribe(observer: any): Subscription {
return this.subject.subscribe(observer);
}
Since you are using Object inside subscribe, this points to current subscribe object, Instead of using subscribe({next:()}) try using this way
component.ts
this.templateParserService.subscribe((result: string[])=>{
if (result !== null) {
this.dataSource = result;
if (this.dataSource && this.dataSource.length) {
this.csvVisible = true;
} else {
this.csvVisible = false;
}
}
},(error: Error)=>{
console.log(error.message);
});

How to pass data from a component to another component

When I click to edit I can edit but when I try to append a kind to the parent it takes the parent infoprmation and not create a new VI.
With angular dialog I made like this but with component I dont know.
This is with dialog
<div class="dropdown-menu-item" (click)="openValueItemEditDialog({valueItem: valueItem})">Edit</div>
This is the TS
openValueItemEditDialog(editOptions: EditOptions) {
this.dialog.open(ValueItemEditDialogComponent, {data: editOptions, disableClose: true});
}
And this is the TS of dialog
constructor(private store: Store<ApplicationState>, #Inject(MAT_DIALOG_DATA) public editOptions: EditOptions) {
}
ngOnInit() {
if (this.editOptions.valueItem) {
this.editedValueItem = _.cloneDeep(this.editOptions.valueItem);
} else {
this.editedValueItem = emptyValueItem();
}
export interface EditOptions {
valueItem?: ValueItem;
appendToParentId?: string;
planning?: number;
}
But without dialog I dont know how to pass the data
showChild = false
edit(editOptions: EditViOptions) {
this.showChild = !this.showChild;
if (editOptions.valueItem) {
return editOptions.valueItem;
} else if (editOptions.appendToParentId) {
return editOptions.appendToParentId;
}
this.activeSelected = this.valueItem.id;
} //this open and closes the component
}
This is the Html of Service matrix row
<app-edit-dialog-vi [showMePartially]="showChild"></app-edit-dialog-vi>
<div *ngIf="valueItem.level < 7" class="dropdown-menu-item" (click)="edit({appendToParentId: valueItem})">Append2</div>
Here is the edit-dialog-vi
<div *ngIf="showMePartially" class="container">
</div>
In the constructor I dont know what to write
This is the TS file and interface what I have created for the Edit vi dialog
constructor(private store: Store<ApplicationState>, public editOptions: ServiceMatrixRowComponent) { }
ngOnInit() {
if (this.editOptions.valueItem) {
this.editedValueItem = _.cloneDeep(this.editOptions.valueItem);
console.log(this.editedValueItem, '***');
} else {
this.editedValueItem = emptyValueItem();
}
export interface EditViOptions {
valueItem?: ValueItem;
appendToParentId?: string;
planning?: number;
}
I don't know if I understood your question well, but you can try this :
ParentHtml
<app-edit-dialog-vi [data]="dataToPass" [showMePartially]="showChild"></app-edit-dialog-vi>
<div class="dropdown-menu-item" (click)="edit(valueItem.level < 7 ? {appendToParentId: valueItem.id} : {valueItem: valueItem})">Edit2</div>
Parent Ts
Add a property dataToPass, and set it to the data you want to send to the child.
showChild = false;
dataToPass: EditViOptions = null;
edit(editOptions: EditViOptions) {
this.showChild = !this.showChild;
if (editOptions.valueItem || editOptions.appendToParentId) {
this.dataToPass = editOptions;
}
this.activeSelected = editOptions.valueItem.id;
}
Child Ts
Add an input named data to get the data sent :
#Input() showMePartially = false;
#Input() data: EditViOptions = null;
constructor(private store: Store<ApplicationState>, public editOptions: ServiceMatrixRowComponent) { }
ngOnInit() {
if (this.data.valueItem || this.data.appendToParentId) {
this.editedValueItem = _.cloneDeep(this.data.valueItem);
console.log(this.editedValueItem, '***');
} else {
this.editedValueItem = emptyValueItem();
}
export interface EditViOptions {
valueItem?: ValueItem;
appendToParentId?: string;
planning?: number;
}
To learn better i will suggest you just look at the below link. It will let you know how to pass data from Parent-> Child and Child-->Parent component in different ways.
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
Hope it gonna help you.
Thanks

Custom validator in Angular 5 dynamic forms

I am creating a dynamic form from a configurable json in Angular 5. Everything is working fine,but i am not able to add a custom validator for a particular field.I am getting an error like
TypeError: v is not a function
Json
{
"key": "age",
"label": "Age",
"required": false,
"order": 4,
"controlType": "textbox",
"validations": ['required', 'minlength'],
"custom":['rangeValidator'],//custom validator function name
"type": "email"
}
Component to make dynamic form controls:
toFormGroup(questions) {
let group: any = {};
questions.forEach(question => {
group[question.key] = new FormControl(question.value || '', this.getValidators(question)
);
});
return new FormGroup(group);
}
getValidators(question) {
let vals = [];
question.validations.forEach((v) => {
if (v == 'required') {
vals.push(Validators.required);
}
if (v == 'minlength') {
vals.push(Validators.minLength(4))
}
});
if (question.custom || question.custom.length > 0) {
question.custom.forEach((va) => {
vals.push(va);
});
}
return vals;
}
Main Component file:
import { Component, OnInit, Input } from '#angular/core';
import { FormGroup, AbstractControl ,FormControl} from '#angular/forms';
function rangeValidator(c: FormControl) {
if (c.value !== undefined && (isNaN(c.value) || c.value > 1 || c.value < 10)) {
return { range: true };
}
return null;
}
#Component({
selector: 'app-question',
templateUrl: './dynamic-form-question.component.html',
styleUrls: ['./dynamic-form-question.component.css']
})
export class DynamicFormQuestionComponent implements OnInit {
#Input() question;
#Input() form: FormGroup;
get isValid() { return this.form.controls[this.question.key].valid; }
constructor() { }
ngOnInit() {
console.log("My form", this.form.value)
}
}
Stackblitz Url
Any ideas,Please help
there
if (question.custom || question.custom.length > 0) {
question.custom.forEach((va) => {
vals.push(va);
});
}
you want to add your custom validators, but in fact you just add to the validators array the string "rangeValidator". So yes v is not a function :)
You should should declare you range validators as a static function of your customs validators like that :
export class CustomValidators {
static rangeValidator(c: FormControl) {
if (c.value !== undefined && (isNaN(c.value) || c.value > 1 || c.value < 10)) {
return { range: true };
}
return null;
}
then import it in and use it like that :
getValidators(question) {
....
if (question.custom || question.custom.length > 0) {
question.custom.forEach((va) => {
vals.push(CustomValidators[va]);
});
}
return vals;
}
see the forked stackblitz
NB : this fork only resolve the current matter. You global example form validation still doesnt work

Get image dimension in angular 2

I am writing code to upload an image file. I need to know the dimensions(height and width) of the image that will be uploaded before I call the function to upload.
Is there a way in angular 2 by which I can extract the image dimension? If so, how?
I created function to get image size
getImgSize(imageSrc: string): Observable<ISize> {
let mapLoadedImage = (event): ISize => {
return {
width: event.target.width,
height: event.target.height
};
}
var image = new Image();
let $loadedImg = fromEvent(image, "load").pipe(take(1), map(mapLoadedImage));
// Rxjs 4 - let $loadedImg = Observable.fromEvent(image, "load").take(1).map(mapLoadedImage);
image.src = imageSrc;
return $loadedImg;
}
interface ISize { width: number; height: number; }
Also you can subscribe on load event in html
<img (load)="loadedImg($event)" [src]="imageSrc"> and get size from it.
With the Angular2 approach, I'll create a custom directive to get the height and width of any element. For img, I'll apply it(directive) in the img tag and whenever I want to get the height & width of an img, I just need click it. You can modify according to your need.
DEMO : https://plnkr.co/edit/3tibSEJCF734KQ3PBNZc?p=preview
directive.ts
import { Directive,Input,Output,ElementRef,Renderer} from '#angular/core';
#Directive({
selector:"[getHeightWidth]",
host:{
'(click)':"show()"
}
})
export class GetEleDirective{
constructor(private el:ElementRef){
}
show(){
console.log(this.el.nativeElement);
console.log('height---' + this.el.nativeElement.offsetHeight);
console.log('width---' + this.el.nativeElement.offsetWidth);
}
}
app.ts
#Component({
selector: 'my-app',
template: `
<div style="width:200px;height:300px">
<img getHeightWidth <!-- here I'm using getHeightWidth directive-->
[src]="source" alt="Angular2"
width="100%"
height="100%">
</div>
`,
})
export class AppComponent {
source='images/angular.png';
}
Simply you can use following code to get the width and height (Resolution) of the Image.
HTML Code
<img #pic [src]="imgURL" (load)="onLoad()>
In Angular
#ViewChild('pic', { static: false }) pic: ElementRef;
onLoad() {
console.log((this.pic.nativeElement as HTMLImageElement).naturalWidth);
console.log((this.pic.nativeElement as HTMLImageElement).naturalHeight);
}
In case if you need to get the image size in ts file:
getImageDimension(image): Observable<any> {
return new Observable(observer => {
const img = new Image();
img.onload = function (event) {
const loadedImage: any = event.currentTarget;
image.width = loadedImage.width;
image.height = loadedImage.height;
observer.next(image);
observer.complete();
}
img.src = image.url;
});
}
Call above method:
const image = {
url: 'https://kalgudi.com/store/assets/images/e-mahila1.jpg',
context: 'Mahila self help group'
}
this.getImageDimension(image).subscribe(
response => {
console.log(response);
}
);
In component.ts
this.uploadService.validateandUploadFile(files, 300, 300);
In service.ts file
import { Injectable } from '#angular/core';
import * as AWS from 'aws-sdk/global';
import * as S3 from 'aws-sdk/clients/s3';
import { BehaviorSubject } from 'rxjs';
FOLDER = '/';
imageUrl = "";
resData: BehaviorSubject<any> = new BehaviorSubject(null);
data = { message: "", data: "" };
constructor() { }
validateandUploadFile(file, Iheight, Iwidth) {
let fileToUpload = file;
if (fileToUpload.type == "image/jpeg" || fileToUpload.type == "image/png" || fileToUpload.type == "image/jpeg") {
//Show image preview
let reader = new FileReader();
reader.onload = (event: any) => {
var img = new Image();
img.onload = () => {
let width = img.width;
let height = img.height;
if (width <= Iwidth && height <= Iheight) {
this.imageUrl = event.target.result;
this.uploadfile(file);
} else {
this.data.message = "You can maximum upload " + Iheight + " * " + Iwidth + " File";
this.data.data = "";
this.resData.next(this.data);
return this.resData;
}
};
img.src = event.target.result;
}
reader.readAsDataURL(fileToUpload);
} else {
this.data.message = "You can't be able to upload file except JPG and PNG format";
this.data.data = "";
this.resData.next(this.data);
return this.resData;
}
}
uploadfile(file) {
if (file != null) {
const bucket = new S3(
{
accessKeyId: '***********************',
secretAccessKey: '**********************************',
region: 'us-east-2'
}
);
const params = {
Bucket: '*********',
Key: file.name,
Body: file,
ACL: 'public-read'
};
var that = this;
bucket.upload(params, function (err, data) {
if (err) {
console.log('There was an error uploading your file: ', err);
return false;
}
console.log('Successfully uploaded file.', data);
that.data.message = "Successfully uploaded file.";
that.data.data = data.Location;
that.resData.next(that.data);
return that.resData;
});
}
}
You have to use JS code to find the height and width of image as follow :
<!DOCTYPE html>
<head>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
function readURL(input)
{
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#image1')
.attr('src', e.target.result);
};
reader.readAsDataURL(input.files[0]);
}
}
function upload()
{
var img = document.getElementById('image1');
var width = img.clientWidth;
var height = img.clientHeight;
alert(width + " : " + height);
//check height and width using above two variables (width/height) in if block and place upload code in if block...
}
</script>
</head>
<body>
<input type='file' onchange="readURL(this);" /><input type="button" value="Upload" onClick="upload()" /><br>
<img id="image1" src="#" alt="your image" height="auto" width="auto" />
</body>
</html>
In above code we have to place selected image in image element, after during upload process check height and width and process to upload.
Thanks...