Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Need to be able to update the $location.hashSearch without triggering route change. #354

Closed
idosela opened this issue May 25, 2011 · 12 comments
Assignees
Milestone

Comments

@idosela
Copy link

idosela commented May 25, 2011

We don't want reload the entire controller and template when the user changes the search criteria.
This will allow us to maintain the current state of the current controller, while making the page book-markable.

@mhevery
Copy link
Contributor

mhevery commented May 26, 2011

The current thinking is that we reload the page on each URL change to make sure that there is no difference between navigating to a URL and opening a link. However this extreme approach is causing issues.

Proposal

  • on $location.hashPath change instantiate new controller
  • on $location.hash change call $render(parameters) method on the controller

Just like now each route will be associated with a URL hashPath, Controller as well as template. If the URL changes which will activate new route, we will instantiate a new controller and then call the $render(parameters) method with url parameters. If the URL changes such that that the same controller remains activated we will call the $render(parameters) with new parameters but on the same controller instance.

This approach will mean that unless the developer puts extra code in the $render() method to handle reusing data, chances are very good that the same code will execute/work wether the user will navigate to the URL or bookmark the URL.

Example

function MyApp($route) {
  $route.when('/Book/:bookId', {template:'rsrc/book.html', controller:BookCntl});
  $route.when('/Book/:bookId/ch/:chapterId', {template:'rsrc/chapter.html', controller:ChapterCntl});
}

function BookCntl(){
  // Executes on new instance -> when hashPath changes
}
BookCntl.prototype = {
  $render: function(properties){
     // Executes multiple times on same instance per URL change as long as hashPath remains same
  }
}

function ChapterCntl(){
}
ChapterCntl.prototype = {
  $render: function(properties){
  }
}

@marcja
Copy link

marcja commented May 26, 2011

Is there an implicit $eval already in the calling code of render or would this require an explicit call to $eval?

@mhevery
Copy link
Contributor

mhevery commented May 26, 2011

@marcja,

In angular all calls have always in implicit call to $eval. The only place where one has to call eval is at the boundries, for example when one is writing their own widget. So no need for $eval it is automatic.

Do you have a better name for this method? I am not sure it should be prefixed with $, but I am thinking yes, since it is angular API that you, as a developer, have to implement.

@vojtajina
Copy link
Contributor

How about creating new controller only when its different than the current one. (not always when hashPath change).

Using your example:

function MyApp($route) {
  $route.when('/Book/:bookId', {template:'rsrc/book.html', controller:BookCntl});
  $route.when('/Book/:bookId/ch/:chapterId', {template:'rsrc/chapter.html', controller:ChapterCntl});
}

When you open /Book/123 new controller BookCntl is created and $render method called.
When you then open /Book/456 or /Book/123?search=true the current controller is reused, only $render is called with new params.

@IgorMinar
Copy link
Contributor

I'm not too crazy about this magic method on the controller. Can't we enhance the route declaration instead?

function MyApp($route) {
  $route.when('/Book/:bookId', {template:'rsrc/book.html',
                                controller:BookCntl, 
                                onHashSearchChange: 'foo'});
}

function BookCntl(){
  // Executes on new instance -> when hashPath changes
}

BookCntl.prototype = {
  foo: function(properties){
     // Executes multiple times on same instance per URL change as long as hashPath remains same
  }
}

@mhevery
Copy link
Contributor

mhevery commented Jun 8, 2011

@IgorMinar, enhancing route declaration is certainly a possibility. By I wonder if the extra level of indirection is worth it? What is your objection to implementin well defined methods.

@IgorMinar
Copy link
Contributor

I think that $render is a bad name, but can't come up with a better one, so the extra level of indirection doesn't force us to come up with a good name.

@mhevery
Copy link
Contributor

mhevery commented Jun 8, 2011

you have to come up with onHashSearchChange. So you are always introducing a new concept. While I am not opposed to your idea, I am wondering if that extra level of indirection is just a sign that we don't fully understand the issue. Hence my concern is adding complexity.

@marcja
Copy link

marcja commented Jun 10, 2011

What about introducing BDD-like events on controllers, such as beforeAll, beforeEach, afterEach, afterAll? beforeAll/afterAll are lifetime events for the route. beforeEach/afterEach are lifetime events for the current hashstate. The logic you would have put in $render would go into beforeEach.

@mhevery
Copy link
Contributor

mhevery commented Jun 13, 2011

Full lifecycle, sounds like a good idea. Do you know the exact events you are looking for?

@ghost ghost assigned mhevery and vojtajina Jun 20, 2011
@vojtajina
Copy link
Contributor

Any update to this issue ?

Currently we destroy the old route and scope always when $location.hashPath / $location.hashSearch changes.
How about reusing them ? So when only hashSearch or param value in the hashPath changes we don't create new route, just update the params...

@IgorMinar
Copy link
Contributor

Well there are two possible solutions that were already implemented:

All of us agreed that neither is a particularly good solution. Misko's solution introduces magical method and convention-over-configuration as well as different behavior of controllers depending on weather they are used with $route or ng:controller. Mine suffers from having two different execution paths in controllers for a given url depending on weather you are changing routes or not.

The approach that requires use of events or event bus sounds like the most ideal, but is also the hardest to implement right now because we don't have any infrastructure for it yet.

IgorMinar added a commit to IgorMinar/angular.js that referenced this issue Aug 19, 2011
In order to avoid unnecesary route reloads when just hashSearch part
of the url changes, it is now possible to disable this behavior by
setting reloadOnSearch param of the route declaration to false.

Closes angular#354
IgorMinar added a commit to IgorMinar/angular.js that referenced this issue Aug 19, 2011
In order to avoid unnecesary route reloads when just hashSearch part
of the url changes, it is now possible to disable this behavior by
setting reloadOnSearch param of the route declaration to false.

Closes angular#354
ggershoni pushed a commit to ggershoni/angular.js that referenced this issue Sep 29, 2015
In order to avoid unnecesary route reloads when just hashSearch part
of the url changes, it is now possible to disable this behavior by
setting reloadOnSearch param of the route declaration to false.

Closes angular#354
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants