0

I have angular 8 application.

And I have a get method. But this method I want to use in several components.

So I made a service of the getter method. But then I get some errors.

So I have the getter method like this:

@Injectable({
  providedIn: 'root'
})
export class GetProfileImageUrl {
  profileImagefile: File;

  constructor(private sanitizer: DomSanitizer) {}

 get profileImageUrlDefault() {
    return this.profileImagefile === null
      ? '/assets/placeholder.jpg'
      : this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(this.profileImagefile));
  }
}

and the component looks like this, where I inject the method:

constructor(
  
    private getImageUrl: GetProfileImageUrl
  ) {}


 get profileImageUrl() {
    return this.getImageUrl.profileImageUrlDefault;
  }

and the template looks like this:

<img [src]="profileImageUrl" width="147px" />

But then I get this error:

core.js:5871 ERROR TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.
    at GetProfileImageUrl.get profileImageUrlDefault [as profileImageUrlDefault] (get-profile-image-url.ts:15)
    at ProfileInformationComponent.get profileImageUrl [as profileImageUrl] (profile-information.component.ts:86)
    at ProfileInformationComponent_Template (profile-information.component.html:3)
    at executeTemplate (core.js:11926)
    at refreshView (core.js:11773)
    at refreshComponent (core.js:13213)
    at refreshChildComponents (core.js:11504)
    at refreshView (core.js:11825)
    at refreshComponent (core.js:13213)
    at refreshChildComponents (core.js:11504)

So what I have to change?

Thank you

So the method is working if I define it directly in the component. But I want to reuse the method in several components.

So if I try it like this:

 profileImageUrlDefault() {
    return this.profileImagefile === null
      ? '/assets/placeholder.jpg'
      : this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(this.profileImagefile));
  }

and I call the method like this:

  get profileImageUrl() {
    return this.getImageUrl.profileImageUrlDefault;
  }

I get this error:

profileImageUrlDefault()%20%7B%20%20%20%20%20%20%20%20return%20this.profileImagefile%20===%20null%20%20%20%20%20%20%20%20%20%20%20%20:1 GET http://localhost:4200/profileImageUrlDefault()%20%7B%20%20%20%20%20%20%20%20return%20this.profileImagefile%20===%20null%20%20%20%20%20%20%20%20%20%20%20%20?%20%27/assets/placeholder.jpg%27%20%20%20%20%20%20%20%20%20%20%20%20:%20this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(this.profileImagefile));%20%20%20%20} 404 (Not Found)
  • This might help: https://stackoverflow.com/questions/27120757/failed-to-execute-createobjecturl-on-url – vill3m Sep 16 '20 at 15:39
  • ? it works if I define the method directly in the component. But because I have several components that are using that method - it will duplicate the code. That is the point. The function works fine. – NiceTobeBottleInfinity Sep 16 '20 at 15:41
  • `profileImagefile` is undefined if you don't set the value later on, but you're checking it for null, so it tries to run `createObjectURL` on undefined, which is not a valid operation. – Heretic Monkey Sep 16 '20 at 15:43
  • Ok. without `get` accessor your service works fine. Now, it's another problem with the way you pass the file link. It's better to use an absolute path here like `/assets/placeholder.jpg'` – ng-hobby Sep 16 '20 at 15:47
  • What i have to change then? – NiceTobeBottleInfinity Sep 16 '20 at 15:47
  • But a user can upload a image.So how I have to change it then? – NiceTobeBottleInfinity Sep 16 '20 at 15:50
  • That error appears to show the contents of the function, URL encoded. I think @ng-hobby is correct that you're better off using functions and calling them as such instead of property getters. – Heretic Monkey Sep 16 '20 at 15:55
  • Yes, oke. But I have done that. I made it as a function. But then I get the error. I have written it in the post. So what I have to change? – NiceTobeBottleInfinity Sep 16 '20 at 15:57

2 Answers2

0

Using a shared service is a good practice. well done. But I think your problem is in the way of calling the profileImageUrlDefault() function in your component. You should try this:

app.component.ts

 constructor(cprivate getImageUrl: GetProfileImageUrl) {}

 get profileImageUrl() {
    return this.getImageUrl.profileImageUrlDefault();
  }

Actually you missed () of your function call on return this.getImageUrl.profileImageUrlDefault statement.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
ng-hobby
  • 2,077
  • 2
  • 13
  • 26
  • Thank you for your reply. But if I call it like a method: (), then I get this error: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? Type 'SafeUrl' has no call signatures.ts(6234) – NiceTobeBottleInfinity Sep 16 '20 at 15:38
  • Yes, You are right.I mean try the `profileImageUrlDefault` without `get` accessor. – ng-hobby Sep 16 '20 at 15:40
  • yes, oke. But then the problem is this: profileImageUrlDefault()%20%7B%20%20%20%20%20%20%20%20return%20this.profileImagefile%20===%20null%20%20%20%20%20%20%20%20%20%20%20%20:1 GET http://localhost:4200/profileImageUrlDefault()%20%7B%20%20%20%20%20%20%20%20return%20this.profileImagefile%20===%20null%20%20%20%20%20%20%20%20%20%20%20%20?%20%27/assets/placeholder.jpg%27%20%20%20%20%20%20%20%20%20%20%20%20:%20this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(this.profileImagefile));%20%20%20%20} 404 (Not Found) – NiceTobeBottleInfinity Sep 16 '20 at 15:42
  • So the method works if I do it directly in the component. But because several components are using that method. It is better to have on central place for it. – NiceTobeBottleInfinity Sep 16 '20 at 15:43
  • ? So what I have to change then? – NiceTobeBottleInfinity Sep 16 '20 at 19:02
0

So this is the soluition:


@Injectable({
  providedIn: 'root'
})
export class GetProfileImageUrl {
  compWindow: any;

  constructor(private sanitizer: DomSanitizer) {
    this.compWindow = window;
  }

  profileImageUrlDefault(profileImagefile: File) {
    return profileImagefile == null
      ? '/assets/placeholder.jpg'
      : this.sanitizer.bypassSecurityTrustUrl(this.compWindow.URL.createObjectURL(profileImagefile));
  }
}

and injecting in component:

  get profileImageUrl() {   
    return this.getImageUrl.profileImageUrlDefault(this.profileImagefile);
  }