2

Is there an Angular pipe which takes a String text, and lets user get an actual value?

String: {"ProductId": "1234", "ProductName": "Computer"}

Expected Pipe:

(item | pipe).productName 
===> results in 'Computer'

(item | pipe).productId
===> results in 1234

Resource:

This following pipe converts an object into json. https://angular.io/api/common/JsonPipe

I need to convert string, and get a member value

3 Answers3

2

I have not seen a pipe like the one you mean but it would probably be something like this if you did it yourself...:

Created this one and tested it...works pretty great using the description data you provided.

@Pipe({
  name: 'jsonParse'
})
export class JsonParsePipe implements PipeTransform {

  transform(value: string, ...args: unknown[]): any {
    return JSON.parse(value);
  }

}

In one of the components I had this defined as a member of the component class:

  data = JSON.stringify({ ProductId: '1234', ProductName: 'Computer' });

and had the HTML like so:

<div>{{ (data| jsonParse).ProductId }}</div>

Im pretty sure you could spice it up with a bit of overloading to give it more functionality for future use...

bloo
  • 1,416
  • 2
  • 13
  • 19
  • actually trying that, however this is giving me syntax error, (item | jsonParse).productName , Identifier 'productName' is not defined. 'string' does not contain such a member –  Mar 03 '21 at 17:28
  • ```ProductName``` is the field you have in your description not ```productName```...lool – bloo Mar 03 '21 at 17:30
  • yeah, tried both ways, (item | jsonParse).ProductName not working either –  Mar 03 '21 at 17:31
  • Interesting, let me try make this work, thank you ey...will get back in a moment – bloo Mar 03 '21 at 17:33
  • great, to make it more typesafe, should we change unknown to string? and any to string? transform(value: string, ...args: string[]): string –  Mar 03 '21 at 18:10
  • No don't, because I do not know what extra arguments you are going to add. The return type is also fine because ```JSON.parse``` returns this type – bloo Mar 03 '21 at 18:12
0

You can either make a custom pipe like Ashwyn called out or just make a function in your component to do the same

Stackblitz

Component.ts

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular ' + VERSION.major;
  str = '{"ProductId": "1234", "ProductName": "Computer"}';

  parseJson(str: string): any {
    return JSON.parse(str);
  }
}

Template.Html

<div>{{parseJson(str).ProductName}}</div>

I would say if you think you're going to need to use similar functionality throughout your app, make a pipe. If this is a one-time thing, just create a function within the component.

mwilson
  • 12,295
  • 7
  • 55
  • 95
  • isn't a pipe better, since its faster? that's what I'm trying to use, rather than function? –  Mar 03 '21 at 17:34
  • You would have to do some benchmarking to measure the speed, but I highly doubt there is any noticeable difference (if any). The main driver for the pipe is encapsulating complexity and reusability. The functionality you're after is very trivial (a one-liner at most). In my opinion, I would be doing this type of data cleansing/formatting upstream instead of trying to make a format you don't to work with work in your template by creating a workaround. For example, if this is coming back from an HTTP call, format the JSON into an object within the response using `.pipe` or something. – mwilson Mar 03 '21 at 17:37
0

This will also work:

Typescript:

export class ToJsonPipe implements PipeTransform {
  transform(value: string): any {
    try {
      return JSON.parse(value);
    } catch {
      return null;
    }
  }
}

HTML:

{{ (item?.request | toJson)?.ProductName }}