Running Angular 1.3.13
base href to load all assets from a specific subdirectory
<base href="/marketing/" />
enable html 5 mode
// remove hash /#/
$locationProvider.html5Mode(true);
Routes are setup like this:
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.otherwise({
redirectTo: '/'
});
Upon loading the application, the following error is thrown n times (I believe per anchor href on the page)
2VM9729 angular.js:11607 TypeError: Cannot read property 'replace' of undefined
at trimEmptyHash (VM9729 angular.js:10564)
at $LocationProvider.$get (VM9729 angular.js:11374)
at Object.invoke (VM9729 angular.js:4185)
at VM9729 angular.js:4003
at getService (VM9729 angular.js:4144)
at Object.invoke (VM9729 angular.js:4176)
at VM9729 angular.js:4003
at getService (VM9729 angular.js:4144)
at Object.invoke (VM9729 angular.js:4176)
at VM9729 angular.js:6485
Debugging this issue, I found at this line:
// rewrite hashbang url <> html5 url
if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
$browser.url($location.absUrl(), true);
}
$location.absUrl()
returns undefined
My GUESS is that the base href is throwing off the matching of routes at $.when('/'), and so is undefined...
BTW, this setup of serving assets from a subdirectory but having the routes relative to root is required for our setup of having 2 separate applications running on the same domain, we just needed to differentiate the static folders from each other and don't want to include those subdirectories in every route.
This may not be a bug but would be nice to have some way of telling angular about how to map routes vs. assets
I have the same problem.
My base href is ru
When I run applucation by
http://myDomain.com/ru
it's all right, but when I use
http://myDomain.com
(without base href) I have an exception
TypeError: Cannot read property 'replace' of undefined
The same for me, also with Angular 1.3.14
Same for me. Any response on this?
I just encountered this issue, however, I'm not using ngRoute in any fashion. My case was that the check for the base url was case sensitive and my url in the browser was lowercase, but in the base is was uppercase.
The function in question that was doing the case sensitive comparison for me was "beginsWith" in $$parseLinkUrl (there's two of those). While it may not be exactly what your case is this is where it parses the absUrl so that would be a good place to see what's happening.
function beginsWith(begin, whole) {
if (whole.indexOf(begin) === 0) {
return whole.substr(begin.length);
}
}
related #11223
it seem the bug is caused by the 814th line in file "src/ng/location.js": $location.$$parseLinkUrl(initialUrl, initialUrl);
the code above send the initialUrl
as param twice, it is weird, so i try to send appBase
as the first param to $$parseLinkUrl
, then the bug fixed.
just want to know this is a correct solution?
@SamHwang1990, that will not work if you use any app routing.
For example, if you have the following:
// From <base> href Url
baseHref = '/username/'
// From $browser.url(), what the user typed in the URL bar
initialUrl = 'http://www.example.com/UserName/additional/path/data/?queryString=something#fragment/data'
// From appBase = serverBase(initialUrl) + (baseHref || '/');
appBase = 'http://www.example.com/username/'
If you pass appBase
as the first param to $$parseLinkUrl
, you will lose all of the routing data, in this case additional/path/data/?queryString=something#fragment/data
.
The two parameters for $$parseLinkUrl
are the absolute URL and the relative URL, and in this case, since the url is from the browser (not an href link in the body) there is not relative URL so the full path is passed for both.
@Chryssie, and anyone dealing with case-sensitivity, you may want to read what I wrote over on https://github.com/angular/angular.js/issues/11223
Same here with angular 1.3.14
Is there a workaround? Is it fixed in 1.4.0? I´m at development status so it would be ok for me to install a unstable version...
Same issue here. Workaround is to set base path to "/" and use full url paths.
https://docs.angularjs.org/guide/$location - see the section on "Relative links" - using "/my-base" and the prior section "HTML link rewriting" example of "/not-my-base/link".
My app configured with:
<base href="Main"/>
$locationProvider.html5Mode(true);
Should be able to have <a href="/Main/Somepage"/> that causes $location.path to change
Should be able to have <a href="/not-my-base/Somepage"/> that causes window.location.href to change (ie: cause a browser refresh).
However when the ng-app is initializing, the routing configuration fails with error stack::
Cannot read property 'replace' of undefined
at trimEmptyHash
In Angular.js line 10551 (for version 1.3.14)
Also tried 1.4.x.
I believe I have this sorted. I'm trying to build angular from scratch to regression test a fix, but running into some issues. Will submit a pull request as soon as I get angular built and tested.
That sounds great @joelmdev
Don't hesitate to ask if you have problems with the build. We always try to make it easier for people to contribute.
Same thing here.
$location.absUrl()
returns undefined, so trimEmptyHash
function in the following code gets an exception:
if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
$browser.url($location.absUrl(), true);
}
Has someone already solved that?
@Narretz I wasted a lot of time trying to get everything to build on Windows and ultimately had to go with an Ubuntu VM. Still working out some bugs with the VM, but I got Angular to build and the unit tests to run. I may need some assistance on creating an e2e test to cover the fix. Any pointers on where I can go to get some advice on that?
@joelmdev
Not knowing what problems you had, I've been using git bash on Windows, maybe you can give this a try if the cl integration is lacking.
Most location tests are unit tests, but a good e2e is always welcome.
The e2e tests are run with protractor (via grunt). You can add your own inside test/e2e: you need both a test file (with normal jasmine specs etc.) and a fixture file, which is the base html for your test. Protractor will automatically wait for angular in your spec file, and then you can inspect the page or change to location etc. See the protractor docs for more about that.
I have this problem also. Can the fix be shared until an updated release is made?
starting at line 10811, replace
var locationPrototype = {
/**
* Are we in html5 mode?
* @private
*/
$$html5: false,
with
var locationPrototype = {
/**
* Ensure absolute url is initialized.
* @private
*/
$$absUrl:'',
/**
* Are we in html5 mode?
* @private
*/
$$html5: false,
@Narretz I believe this fix requires an integration test, I don't see how to isolate it enough for a unit test. Would you agree?
@joelmdev
Your solution fixed our problem
file:/// load of our angularJS app in an UIWebView
I'll submit a pull request sometime this week and see where it gets me.
This appears to be fixed, perhaps inadvertently, in the latest version available via Nuget. Can someone else verify?
@joelmdev you mean in 1.4.1? The only location fix in it is this: https://github.com/angular/angular.js/commit/91b602263b96b6fce1331208462e18eb647f4d60
Still have this in 1.4.1.
Still seeing this issue in 1.4.1 and installed 1.4.2-build.4082+sha.1ce5d21
from bower and this issue is still present. It breaks the entire page from loading.
Running into this as well. So dang frustrating.
Still happening in 1.4.1 but I can confirm that @joelmdev's $$absUrl
change to locationPrototype
fixes the problem.
After further review I found my error. It was due to 301 redirects setup hitting a route outside of the base tag.
One way to recreate the bug is as follows. Create a base tag of <base href="/new/page/" />
and then view /old/page/
and make sure all of the application assets resolve. You may get 404's due to the conflicting base tag.
The flow of the bug starts at $location.$$parseLinkUrl
.
Due to the mismatching url's, /old/page/
and new/page/
, all of the if
checks in LocationHtml5Url.$$parseLinkUrl
fail and subsequently the call to $$parse
never gets invoked.
Because $$parse
was never called, no value for $$absUrl
is set on locationPrototype
. This is what @joelmdev's fix was solving.
With locationPrototype.$$absUrl
being undefined
, any calls to $location.absUrl
also return undefined
.
This in turn cause trimEmptyhash
to throw the following:
Uncaught TypeError: Cannot read property 'replace' of undefined
trimEmptyHash @ angular.1.4.1.js:11259
$get @ angular.1.4.1.js:12097
invoke @ angular.1.4.1.js:4443
(anonymous function) @ angular.1.4.1.js:4261
getService @ angular.1.4.1.js:4402
invoke @ angular.1.4.1.js:4434
(anonymous function) @ angular.1.4.1.js:4265
forEach @ angular.1.4.1.js:336
createInjector @ angular.1.4.1.js:4265
doBootstrap @ angular.1.4.1.js:1621
bootstrap @ angular.1.4.1.js:1642
(anonymous function) @ (index):48
trigger @ angular.1.4.1.js:2989
eventHandler @ angular.1.4.1.js:3264
In regards to solving the bug at hand, there is already some documentation in regards to ignoring routes outside of the app.
We do a preventDefault for all urls that are part of the angular application,
in html5mode and also without, so that we are able to abort navigation without
getting double entries in the location history.
I believe this approach should be extended to take into account a conflicting base
tag and the given route.
I propose that an additional check be added to LocationHtml5Url.$$parseLinkUrl
and throw accordingly. Perhaps something like:
throw $locationMinErr('rtbscnflct', 'The route you are trying to view {0}, is in conflict ' +
'with the value of the base tag {1}', url, appBase);
Any update on getting @joelmdev's fix merged in? It solved our site not loading in IE9. (Thanks!)
I still haven't had a chance to create the pull request. I'm sure it'll get
denied because I don't have any tests to cover it.
On Wed, Jul 29, 2015 at 7:58 PM, Jordan Buckley [email protected]
wrote:
Any update on getting @joelmdev https://github.com/joelmdev's fix
merged in? It solved our site not loading in IE9.—
Reply to this email directly or view it on GitHub
https://github.com/angular/angular.js/issues/11091#issuecomment-126131926
.
@joelmdev encounterd this problem aswell with an IIS Website (MVC 4 with Angular Views).
www.domain.de/SubPath/view.
If I browse: www.domain.de/Subpath/view the error occured.
If i browse: www.domain.de/SubPath/view -> everything is fine
With your fix it worked, maybe you can use this to cover the test?
Greetings & Thanks for your fix.
@graphefruit, If you're dealing with a case-sensitive discrepancy between your URL and your
Still, Angular probably shouldn't crash if it encounters a base path that doesn't match the browser's URL, so @joelmdev's patch would fix that problem.
Is there any way to implement @joelmdev 's fix without modifying original sources? And are there any adverse effects to this fix I should be aware of before proceeding?
Seems strange that the framework crashes when using a page outside of a base url ..
Any news about fix for this bug?
My workaround was to keep the base href at "/" and to prepend the actual base to each route definition.
This is the only way at the moment to get angular with ngRoute to work unless all of your urls are inside the base href.
One of the things I like about Angular is that it doesn't need to be used only in SPA. Most of us have normal websites with javascript on it. Some URLs have routes, some are normal server side rendered pages with angular magic sprinkled on it.
My case is a bit different.
I have an application which should work both in html5 and Hashbang mode:
$locationProvider.html5Mode(true).hashPrefix('!');
When I access it via html5 url like http://sodr/ru/home
it works,
but when I use a variant with hashprefix like http://sodr/ru#!/home
it fails with error:
Uncaught TypeError: Cannot read property 'replace' of undefined in angular.js:11345
while I expect that angular will redirect/rewrite url to http://sodr/ru/home
.
My <base>
is set to 'http://sodr/ru/'
Ideas?
P.S. Proposed solution from https://github.com/angular/angular.js/issues/11091#issuecomment-87779905 fixes this problem.
http://sodr/ru/#!/home http://sodr/ru#!/home should work I think.
You need the trailing slash if that's what your base is set to.
On Wed, Aug 26, 2015 at 11:22 PM Artiom Neganov [email protected]
wrote:
My case seems a bit different.
I have an application which should work both in html5 and Hashbang mode:$locationProvider.html5Mode(true).hashPrefix('!');
When I access it via html5 url like http://sodr/ru/home it works,
but when I use a variant with hashprefix like http://sodr/ru#!/home it
fails with error:Uncaught TypeError: Cannot read property 'replace' of undefined in angular.js:11345
is set to 'http://sodr/ru/' Ideas?
—
Reply to this email directly or view it on GitHub
https://github.com/angular/angular.js/issues/11091#issuecomment-135173288
.
I'm almost embarrassed to offer this hack as a workaround solution to this problem, but I'm finding it useful so far and thought that it might benefit someone here.
If before you load angular onto the page, you put
var nativeGetElementsByTagName = document.getElementsByTagName;
document.getElementsByTagName = function(query) {
if (query === 'base') {
return [];
} else {
return nativeGetElementsByTagName.apply(this, arguments);
}
}
then angular will be fooled into thinking that there is no base tag at all. And then the error referenced in this issue does not happen.
Completely ignoring the base tag may or may not be what you really want in the end, but if it is then this works :p
@joeldenning I'll give this a shot. If this fixes the problem until my fix is committed and approved, then it's a great workaround. I'm having to keep custom copies of angular source in my repo instead of letting a package manager restore them for me as well as apply the same fix in place whenever updates are released.
I know that the fix I provided has worked for everyone that has tried it and doesn't seem to cause any regression bugs, but I'm just not familiar enough with Angular testing to provide the necessary test coverage to submit the change as a pull request.
I am using angular 1.4.3. The issue for my case is base tag case sensitive.
Eg: path is /aBc/test
while base tag setup as /ABC/
then angular throw error that described in this issue. But works fine if base setup as /aBc/
.
My application is base on server side MVC, thus I have ability to change base tag value base on query URL. Thus resolved issue.
Challenge is angular base route is case sensitive while my server is case insensitive.
@Nness set route to be case insensitive:
caseInsensitiveMatch: true
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
@crucialfelix
I'm using ui-router not ngRoute. That config is no use. Take look the issue under uirouter:
https://github.com/angular-ui/ui-router/issues/197
@joelmdev
your trick helped me and I found exact issue in my app.
I have used "/demo/" as my base URL and I was tried to access my app using "www.domainname.com" got the error. The error is gone when I access the app using the URL "www.domainname.com/demo".
This could help someone.
Wondering if this is related to the issue I'm having currently.
$location.absUrl()
returns a value in Chrome but not in IE.
I'm using a base url and html5 mode.
(Almost) The same as codedbypaul here,
$location.absUrl()
Returns a correct value in Chrome but not Firefox
still have this in 1.5.5. any plan about this issue?
IIRC a PR was merged into master recently that initializes $$absUrl
. It might take care of this.
@lili21, can you check if the problem still exists on the current snapshot ?
The PR I had in mind is #14488, but it hasn't been merged yet. (Thx @Narretz for pointing it out.)
You should keep an eye on that one, @lili21.
@joelmdev Saved my bacon my friend, this really needs fixing.
First time I've ran into the issue and I've used HTML5Mode on lots of different apps, really need to find out whats causing it.
I have the same problem in last snapshot as well - AngularJS v1.5.7-build.4844+sha.cd3673e.
Is there any solution?
@jdimov, the fixed is tracked at #14488.
Thanks. I think in 1.5.6 is working fine.
On Mon, Jun 6, 2016 at 3:54 PM, Georgios Kalpakas [email protected]
wrote:
Closed #11091 https://github.com/angular/angular.js/issues/11091 via
b9ac336
https://github.com/angular/angular.js/commit/b9ac3362ee2a7c44417cd9f414ba0c8f40288dfd
.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular.js/issues/11091#event-682797753, or mute
the thread
https://github.com/notifications/unsubscribe/AC3clEx5oIhyALbzKbznuxVXSwKqCvBzks5qJBihgaJpZM4Dhxwb
.
Glad this got fixed. I would have committed the fix a long time ago, but getting an environment setup for angular contribution development proved prohibitively time consuming.
Most helpful comment
Same thing here.
$location.absUrl()
returns undefined, sotrimEmptyHash
function in the following code gets an exception:Has someone already solved that?