0

Applications using angular6 and node.js ran into a problem, which is now writing the part that is responsible for uploading pictures on the server, created the imagePreview = "" variable (yes, it is empty by default)

ERROR in src/app/categories-page/categories-form/categories-form.component.ts(74,7): error TS2322: Type 'string | ArrayBuffer' is not assignable to type 'string'. [1] Type 'ArrayBuffer' is not assignable to type 'string'.

That's what I have on line 74, I don’t understand where the error is (WebStorm emphasizes reader.result)

reader.onload = () => {
      this.imagePreview = reader.result
    }

Please tell me how to fix

The code of the component that is responsible for downloading images:

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Params} from "@angular/router";
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {CategoriesService} from "../../shared/services/categories.service";
import {switchMap} from "rxjs/operators";
import {of} from "rxjs";
import {MaterialService} from "../../shared/classes/material.service";
import {Category} from "../../shared/interfaces";

@Component({
  selector: 'app-categories-form',
  templateUrl: './categories-form.component.html',
  styleUrls: ['./categories-form.component.css']
})
export class CategoriesFormComponent implements OnInit {

  @ViewChild('input') inputRef: ElementRef
  form: FormGroup
  image: File
  imagePreview=''
  isNew= true
  category: Category

  constructor(private route: ActivatedRoute,
              private categoriesService: CategoriesService) { }

  ngOnInit() {
    this.form=new FormGroup({
      name:new FormControl(null, Validators.required)
    })

    this.form.disable()

    this.route.params
      .pipe(
        switchMap(
          (params: Params)=>{
            if(params['id']){
              this.isNew=false
              return this.categoriesService.getById(params['id'])
            }
            return of (null)
          }
        )
      )
      .subscribe(
        (category: Category)=>{
          if(category){
            this.category = category
            this.form.patchValue({
              name: category.name
            })
            this.imagePreview=category.imageSrc
            MaterialService.updateTextInputs()
          }

          this.form.enable()
        },
        error=>MaterialService.toast(error.error.message)
      )
  }

  triggerClick(){
    this.inputRef.nativeElement.click()
  }

  onFileUpload(event: any){
    const file = event.target.files[0]
    this.image = file

    const reader = new FileReader()

    reader.onload = () => {
      this.imagePreview = reader.result as string
    }

    reader.readAsDataURL(file)
  }

  onSubmit(){

    let obs$

    this.form.disable()

    if(this.isNew){
      obs$ = this.categoriesService.create(this.form.value.name, this.image)
    } else {
      obs$ = this.categoriesService.update(this.category._id, this.form.value.name, this.image)
    }

    obs$.subscribe(
      category =>{
        this.category = category
        MaterialService.toast('Изменения сохранены!')
        this.form.enable()
      },

      error=>{
        MaterialService.toast(error.error.message)
        this.form.enable()
      }
    )
  }
}

Create and edit

create(name: string, image?:File) : Observable<Category>{
    const fd = new FormData()

    if(image){
      fd.append('image', image.name)
    }

    fd.append('name', name)
    return this.http.post<Category>('/api/category', fd)
  }

  update(id: string, name: string, image?:File) : Observable<Category>{

    const fd= new FormData()
    if(image){
      fd.append('image', image.name)
    }
    fd.append('name', name)
    return this.http.patch<Category>(`/api/category/${id}`, fd)
  }
4
  • 2
    well, reader.result is a string | ArrayBuffer and this.imagePreview is a string. You haven't provided enough information for anyone to know what reader is. If it's a ReadbleStream or similar, make sure it's finished reading and either dump it to string or force its typing to string: reader.result as string Commented Dec 12, 2018 at 20:51
  • @joh04667 I changed a little now, now the line has the form this.imagePreview = reader.result as string Yes, now it does not give an error, but the problem is that the variable imagePreview it transmits empty, and must transmit a link to the image Commented Dec 12, 2018 at 20:59
  • Sounds like it's still an ArrayBuffer, hence the tuple typing. You need to decode it first Commented Dec 12, 2018 at 21:07
  • @joh04667 With this difficult, I just started to study, I will try to update the question now and add the code that is responsible for downloading pictures Commented Dec 12, 2018 at 21:13

1 Answer 1

1

ArrayBuffer as string may result in data truncation (would have to test).
So you have to explicitly cast it, as to tell the compiler "I know what I am doing".

Try this, it works for me:

reader.onload = () => {
    this.imagePreview = reader.result as string;
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.