Custom encoding for urls using Angular 2 Router (using a + sign in place of a space)

后端 未结 3 2208
臣服心动
臣服心动 2020-12-09 12:39

I am using an Angular 2 Router to update the query params in a URL for a search application. I am attempting to replace spaces in a query with + signs. However, + signs are

相关标签:
3条回答
  • 2020-12-09 12:53

    I tried @Noahs solution in Angular 9.1 for avoiding that a ? is replaced by %3F:

    However, this did not work:

    class CustomUrlSerializer implements UrlSerializer {
      parse(url: string): UrlTree {
        return this.defaultSerializer.parse(url)  
      }
    
      serialize(tree: UrlTree): string {
        return this.defaultSerializer.serialize(tree).replace(/%3F/g, '?');
      }
    }
    

    Angular had complained with following error message

    client:159 src/app/app.module.ts:36:17 - error TS2339: Property 'defaultSerializer' does not exist on type 'CustomUrlSerializer'.
    

    The following code has worked for me, though:

    class CustomUrlSerializer extends DefaultUrlSerializer {
      parse(url: string): UrlTree {
        return super.parse(url)  
      }
    
      serialize(tree: UrlTree): string {
        return super.serialize(tree).replace(/%20/g, '+');
      }
    }
    

    There, I have replaced:

    implements UrlSerializer --> extends DefaultUrlSerializer
    this.defaultSerializer   --> super
    

    Note: I have removed the following back-translation, since it replaces ? by %3F before routing an URL, but we want to keep it in this case:

      parse(url: string): UrlTree {
        url = url.replace(/\?/g, '%3F'); // <--- removed
        ...
    
    
    0 讨论(0)
  • 2020-12-09 13:11

    I ran into an issue specifying the custom provider. There was apparently a circular dependency when compiling with the --prod flag causing an error with the text: useClass cannot by null. This is how I worked around that error:

    In AppModule, define the following:

    const customUrlSerializer = new CustomUrlSerializer();
    const CustomUrlSerializerProvider = {
        provide: UrlSerializer,
        useValue: customUrlSerializer
    };
    

    Then in the providers array, add the provider you specified above.

    ...
    providers: [CustomUrlSerializerProvider]
    ...
    
    0 讨论(0)
  • 2020-12-09 13:16

    I was able to find a solution to my problem. You can make own custom url serializer by implementing the UrlSerializer class.

    Custom Url Serializer

    Create a custom url serializer like this:

    class CustomUrlSerializer implements UrlSerializer {
        parse(url: string): UrlTree {
            // Custom code here
        }
    
        serialize(tree: UrlTree): string {
            // Custom code here
        }
    }
    

    Then, you just need to provide the CustomUrlSerializer in place of the UrlSerializer, which you can place in the AppModule providers array after importing both serializers.

    providers: [
        { provide: UrlSerializer, useClass: CustomUrlSerializer },
        ...
    ]
    

    Now, when you call router.navigate or router.navigateByUrl, it will use your custom serializer for parsing and serializing.

    Using + signs as spaces

    To parse + signs as spaces:

    parse(url: string): UrlTree {
        // Change plus signs to encoded spaces
        url = url.replace(/\+/g, '%20');
        // Use the default serializer that you can import to just do the 
        // default parsing now that you have fixed the url.
        return this.defaultUrlSerializer.parse(url)  
    }
    

    And for serializing:

    serialize(tree: UrlTree): string {
        // Use the default serializer to create a url and replace any spaces with + signs
        return this.defaultSerializer.serialize(tree).replace(/%20/g, '+');
    }
    

    DefaultUrlSerializer

    0 讨论(0)
提交回复
热议问题