0

In Angular 5, the Router/ParamMap object is immutable. It can be retrieved from the route and used in a component. However, I have a use case for which modifying the ParamMap would be convenient (and it worked fine with Angular 4).

Previously, I used the convertToParamMap function to convert an Object to a ParamMap. Since updating to Angular 5, the resulting ParamMap object's private params member loses its prototype and generates an error when I call the resulting ParamMap's .get(key) method.

const params = this.routeParams.keys.reduce( (pv: Params, cv) => { pv[cv] = this.routeParams.get(cv); // <- Error on second call return pv; }, Object.create(null) as Params ); params["changedKey"] = newValue; this.routeParams= convertToParamMap(params); 

this.routeParams is initially populated from a call to the ActivatedRoute instance's queryParamMap method and simply setting my component's routeParams member to the returned ParamMap instance.

On my first pass through the code above, everything works fine. On the second pass, after I've updated the routeParams member with the convertToParamMap function, I receive this error:

Object doesn't support property or method 'hasOwnProperty' 

Via the debugger, the .get(cv) call is internally calling the .has(cv) method, which then calls this.params.hasOwnProperty(name) (this = the ParamMap object and name = cv). I'm thinking this is a bug in Angular 5, but I'm looking for an alternative or workaround until it gets fixed.

Any suggestions?

3
  • May i ask what that "usecase" possibly could be? Because, to be honest, this sounds awkward and awful - no offense :/ if you want to change the params, go ahead and change the route and its params. what you are doing is dis-syncing the actual routes and the params you're working on. this can not be a good idea, ever. Commented Feb 19, 2018 at 18:09
  • Pagination - specifically changing the current page or page size. In neither case is a new route being called, so to keep the route parameters used elsewhere in the component synchronized with the displayed content, I had to manually add code for the purpose. There's probably a better way, but this is my first Angular 2+ project with only a few, small AngularJS projects for prior experience. Commented Feb 19, 2018 at 21:30
  • If you want to change the pageSize oder selectedPage you can either just add it to your route in the first place (would be the best solution, since a refresh of the page would result in the same content if you persist it in the route) when you call the same route just with different params, the route will not reload, it will just update the routeParams observable - or just use normal class variables for it. there's no reason to hack it into the route params, if they aren' route params in the first place. hope i could help :) Commented Feb 20, 2018 at 9:02

1 Answer 1

1

I'm not so sure this is the best way to go, but it's working for me.

Instead of Object.create(null) as Params, I'm creating the initial value like this:

const initialValue = Object.create((this.routeParams as any).params.__proto__); 

This creates an "empty" object whose prototype matches that of the original, private params object, so after calling the convertToParamMap function, the resulting ParamMap instance's internal params object has the hasOwnProperty(name) method.

Personally, I don't like calling private members from outside the object which contains them, but this works, so I'll be using it until a better option comes along.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.