All,
I am developing an Angular app (not my first) within an existing JavaScript application that is primarily based in jQuery and Django templates.
In order to get to my Angular application from within the existing application, the URL will look like this:
/existing-application/#myapp/myapp
I realized early that I would have to avoid the injection of $location anywhere in my application or else have Angular become utterly confused with the existing # (hashtag) in the URL.
I have reached a point where this is no longer an option. Therefore, I am setting html5Mode: true and am working with the <base href="" /> header tag to try and find a solution.
However, the closest I have come to having this approach working results in a URL that looks like this after my page renders:
/existing-application/#myapp%2Fmyapp
I currently have a base tag of:
<base href="/existing-application/#myapp/myapp" />
This will load the Angular app. successfully but the URL is then rewritten automatically to:
/existing-application/#myapp%2Fmyapp
Which causes all sorts of problems within and outside of my Angular application.
I have read some reports of bugs wherein there is an issue with $location.rewrite that causes the trailing '/' to become escaped.
I have attempted to work around this issue in several ways, from modifying the <base /> tag, calling $location.path('/existing-application/#myapp/myapp) on page load, using $routeProvider, changing the hashPrefix, and it seems the closest I can ever come to is the escaped trailing slash.
Changing the hashPrefix to '!' merely resulted in:
/existing-application/#!#myapp/myapp
Any advice on what to try next? I am not opposed to not using html5Mode, but without doing so I don't believe this approach will ever work.
Thank you.
Config Block:
.config(['$locationProvider', '$interpolateProvider', '$websocketProvider',
function($locationProvider, $interpolateProvider, $websocketProvider) {
// inject meta 'base' href into <head> tag
$('head').append('<base href="/existing-application/#myapp/myapp" />');
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false,
requireBase: true
});
Angular Information:
Angular v. 1.3.1
Related
I have this strange issue with ASP.NET Core 3.1 that I don't have in my ASP.NET 4 applications where if I access my application via
http://example.com/Application/
then everything works ok, but if I try to go to
http://example.com/Application (no trailing slash)
then client-side relative addresses resolve to http://example.com/Resource instead of http://example.com/Application/Resource.
I had similar issues referring to the root of the application. For example, /Resource seems to mean relative to the domain, and so yields http://example.com/Resource. Resource by itself correctly yields http://example.com/Application/Resource. But how to refer to the "root" itself? Redirecting to the empty string seems to refresh the page instead of redirecting to the application root.
I got around that by using ., and by using ./Resource instead of Resource. This seems to work in almost all cases, except when accessing the application without the trailing slash.
When accessing http://example.com/Application, AJAX calls targeting URLs of the form ./Method?handler=name result in the request http://example.com/Method?handler=name (missing the Application part of the path).
How do I get client-side relative addresses to consistently refer to the correct application root address? Or is it possible that this is normal behaviour?
You need to set the base url in your main template (_Layout.cshtml in ASP.NET Core MVC) to the application path.
In _Layout.cshtml add
<base href="~/"/>
~/ is your applications path (also called web root) that ASP.NET Core will replace with http://example.com/Application. Generally if you need application relative paths you should always do .
That may proof a bit difficult when static json files are involved, so <base href="..."/> should work in this cases
Try this:
function stripSlashEnds(url){
return url.replace(/^\/|\/$/g, '');
}
console.log(stripSlashEnds('http://example.com/Application/')+'/'+stripSlashEnds('/anotherFile/'));
console.log(stripSlashEnds('http://example.com/Application')+'/'+stripSlashEnds('/anotherFile'));
Notice that stripSlashEnds just removes forward lashes from the beginning and end of a String. You'll have to +'/' add one.
So I'm running into a problem with Angular 1.3.15 and the $locationProvider. Every time I turn html5mode on I get a TypeError: Cannot read property 'replace' of undefined error. If I leave html5mode off, everything works fine.
My directory structure is like so (4.DEV being a versioned directory name):
public /
- index.html
4.DEV /
css /
js /
images /
partials /
etc...
I have a base tag set like this:
<base href="/4.DEV/">
And I'm configuring the $locationProvider like so:
$locationProvider.html5Mode({ enabled: true });
If I change the base tag href to "/" Angular doesn't have any issues (but my assets don't load). I suspect that the issue Angular is having deals with the fact that my index.html file is one directory up from the rest of the site.
For reasons I won't list here, I can't change this dir structure and I REALLY don't want to change the base tag (because I don't want to manually stick a version number into all these files). I also want to leave html5mode on.
Does anyone have a solution for this problem? Is there any way for me to MANUALLY set the "base href" for Angular, but leave the tag alone for all my static assets?
So, it looks like Angular's inner workings are tightly coupled to the href of the tag which results in major issues if you have a directory structure that's a bit unconventional like mine.
Stumbled across this Github thread where people are asking for a feature to change this and #greglockwood posted a fix.
With his fix, the tag can work for your static assets while you provide your own set "baseHref" for Angular's stuff.
Worked like a charm for me! Hope this helps anyone who stumbles across this!
I am creating a simple website with a single layout in Asp.Net MVC 4. The layout has Javascript tags in the head like so:
<script src=#Url.Content("/Scripts/jquery.min.js")></script>
<script src=#Url.Content("/Scripts/jquery.dropotron.min.js")></script>
<script type="text/javascript" src=#Url.Content("/Scripts/jquery.slidertron.min.js")></script>
<script src=#Url.Content("/Scripts/skel.min.js")></script>
<script src=#Url.Content("/Scripts/skel-layers.min.js")></script>
<script src=#Url.Content("/Scripts/init.js")></script>
This renders fine when I first load the website/page.
The project uses the typical URL/Home/Index route as the default - but when I call this explicitly by adding '/Home/Index' to the URL the page is rendered without any styling. Any page other than the home as it loads is rendered without style even though they are all just views being injected into this same layout with this same Javascript in the head.
Any ideas why the Javascript isn't being rendered in all of my views?
The only thing that can really cause this is using a relative URL to reference the file. When just loading the domain without a path, a reference like Scripts/foo.js will properly be retrieved at the URL: http://domain.com/Scripts/foo.js. However, with a path like /Home/Index, the URL then becomes http://domain.com/Home/Index/Scripts/foo.js, which is obviously not correct.
However, in your case here, you're not using completely relative paths, as each is prefixed with / which should cause it to always reference from the site root, despite the current URL path. If we are to assume that you copied and pasted this directly from your project, I'm a bit at a loss how you could be experiencing this issue. First, verify that the code you posted here is in fact what you have in your layout. Then, make sure that the views are using the correct layout, and that you've done silly things like saved the file in case you made changes recently. Short of that, try doing a hard refresh in your browser and/or clear the cache, to make sure it's not simply loading stale pages.
We have a product that is a widget people load onto their site, which consists of a single JS file that also needs angular to run, so angular is bundled into the JS file.
However, if a site already is using and loading angular themselves, when they load our widget they get an error which kills everything with the following:
WARNING: Tried to load angular more than once
Which makes complete sense since angular was indeed loaded more than once.
What we'd like to do is either of the following:
In our script, rename / namespace angular so it does't conflict with
the host sites already loaded angular, or
Detect if angular is
already loaded, and if so don't load angular ourselves.
To show examples of our code would be difficult since it's spread over about 20 files etc, however it's based off the following angular seed project which uses requirejs to load everything, then we're compiling to a single file: https://github.com/tnajdek/angular-requirejs-seed
Would really appreciate any feedback / tips / solutions
NB This is not a duplicate of any "check if angular loaded correctly" type questions, angular is packaged inside our widget js, the issue comes when angular is also already loaded by the parent page. We need a way to rename angular inside our package.
I'd advise taking a look at this answer, it has to do with a chrome extension running in the same circumstance. The idea here is to separate your loading of angular from the website's, and it assumes that your widget will be loaded after the main content of the page has been loaded.
If you are loading in html content with an ng-app directive or ng-controller, wrap your html content in a container with ng-non-bindable as an attribute.
Angular looks immediately for an element with the ng-app attribute when you load in angular.js. If two ng-apps are present i.e., on your site, and the widget, it will cause errors. Defer the parsing with: window.name = "NG_DEFER_BOOTSTRAP!" + window.name; Then load in your script.
Once your script has loaded, set window.name to '' or whatever it was before.
Individually bootstrap (the term for angular finding an ng-app attribute) your html content using:
var appRoot = document.querySelector('#id');
angular.bootstrap(appRoot, ['angularModuleName']);
And that should do it... Caveat, I have no idea how this would work if your widget Angular is on a different version than the client website, and I've only made it work with extensions, which are a little bit different because they live in their own isolated 'worlds'.
That being said, I feel like this should get people going in the right direction when dealing with this problem.
I'm building an Adobe AIR application with AngularJS. And have quickly come across a problem in that Angular can't see partials below a certain level and any $http resources.
I've read here: How to Adjust Angular's URL matching pattern that this is because of the way Angular looks at URLs instead of using app:/ but in 2.0+ it no longer has a SERVER_MATCH so I can't use that regex... if that's even the issue anymore?
Basically if I have a index.html like:
<div ng-include="'partials/header.html'"></div>
<div ng-view></div>
<div ng-include="'partials/footer.html'"></div>
It will find those two includes fine! But if in header I have:
<div class="header">
<div ng-include="'partials/header-nav.html'"></div>
</div>
Angular won't see that header-nav in Adobe AIR, because it seems to lose where partials folder is in relation to the rest of the application... I'd assume that all resources also break for this same reason!
This also doesn't work:
phonecatServices.factory('Phone', ['$resource',
function($resource){
return $resource('phones/:phoneId.json', {}, {
query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
});
}]);
Even if I was to call this on the index route, it won't find the JSON file as the factory doesn't know where to find the file...
Setting <base href="app:/"> doesn't fix it either but also breaks the links so that's not a solution...
Any ideas? I'm assuming it's something simple...
This sounds more like server issue then angular.
Are you using paths with hashes? If no, try to, maybe bowser is confused by changing the address bar path and relative urls.
Are you using grunt to build the project? It's worth a try, and then you can use grunt-angular-templates to build them into one js file. There really isn't any reason to make multiple requests for html form you production env.
Load your index.html from the web server.
Then all your resources will be loaded relative to that including the angularJS which will load things like templates.
You can use StageWebView as shown below:-
var webView:StageWebView = new StageWebView();
public function StageWebViewExample() {
webView.stage = this.stage;
webView.viewPort = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight );
webView.loadURL( "http://localhost:9000/app/index.html" );
}
Other options are included in my comments to OP's questions but this should serve the solution well in the constraints of the problem defined by OP.