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

ngAppRoot #3102

Open
geddski opened this issue Jul 1, 2013 · 21 comments
Open

ngAppRoot #3102

geddski opened this issue Jul 1, 2013 · 21 comments

Comments

@geddski
Copy link
Contributor

geddski commented Jul 1, 2013

A new directive to make it easier to run Angular in a subdirectory.

<html ng-app="app" ng-app-root="/myContext"></html>

@IgorMinar the components that should be affected are $location, $routeProvider, $resource, and $http. Have I missed any?

@petebacondarwin
Copy link
Member

Can we change the name to ng-app-base - to better map to the previous
idea of using base[href] and to prevent confusion with $rootScope and root
element?

On 1 July 2013 07:15, Dave Geddes notifications@github.com wrote:

A new directive to make it easier to run Angular in a subdirectory.

@IgorMinar https://github.com/IgorMinar the components that should be
affected are $location, $routeProvider, $resource, and $http. Have I
missed any?


Reply to this email directly or view it on GitHubhttps://github.com//issues/3102
.

@petebacondarwin
Copy link
Member

Oh, just read your comment in #2805 (comment).

I still think ng-app-root is confusing. Perhaps ng-app-root-url?

@Narretz
Copy link
Contributor

Narretz commented Aug 22, 2013

This would be extremely helpful. What are the main difficulties with that? Naively thinking, every component that loads a template or similar just needs to prepend the app base url.

@pholly
Copy link
Contributor

pholly commented Oct 15, 2013

As of angular 1.2.0 rc2 the only way to make html5mode work in non-pushstate browsers if your app is in a subdirectory is to use the <base href="" > tag. So the ability to specify app root in another way would be great.

@drozzy
Copy link

drozzy commented Dec 5, 2013

@pholly This does not fix the issue of angular app being in a subdirectory. It is completely broken if using ui-router (which generates urls relative to the root / and not the base href).

Also, is anyone still interested in this? How did you solve your problems? This issue seems to have died...

P.S.: Issue #2805 seemed very relevant and much easier to implement. Did anyone succeed?

@Narretz
Copy link
Contributor

Narretz commented Dec 19, 2013

+1

@pholly
Copy link
Contributor

pholly commented Dec 19, 2013

@drozzy @Narretz I have it all working. Here are my settings:

The root of my app is /Library

Module Config

Set html5Mode

appModule.config( ['$locationProvider', function ($locationProvider) {
    $locationProvider.hashPrefix('!');
    $locationProvider.html5Mode(true);
}]);

Make sure all paths are lowercase so we can match routes

appModule.config(function ($urlRouterProvider) {
    // This is taken from a post somewhere here on the forums
   // I modified it so it doesn't return a url. Rather it changes the location directly. 
   // I only wanted the path to be lowercased so my ids in query string parameters don't get lowercased.
  // So rather than reconstructing the url to return I just set the $location.path and replace the $location.
    $urlRouterProvider.rule(function ($injector, $location) {
        var path = $location.path(), normalized = path.toLowerCase();
        if (path != normalized) {
            //instead of returning a new url string, I'll just change the $location.path directly!
            $location.replace().path(normalized);
        }
    });
})

Routing table

appModule.config(['$stateProvider', function ($stateProvider) {
    var urlRoot = '/library';

    $stateProvider
        .state('munipro', {
            url: urlRoot + '/munipro',
            templateUrl: serverProps.templateUrlRoot + '__MuniproPartial',
            controller: 'MuniproController'
        })
        .state('munipro.content', {
            url: '/?stateAbbr&clientName&contentTypeId&productName&nodeId'
        })
        .state('states', {
            url: urlRoot + '?searchText&codeArchiveDate',
            abstract: true,
            templateUrl: serverProps.templateUrlRoot + '__StatesWrapperPartial',
            controller: 'StatesWrapperController'
        })
        .state('states.stateListing', {
            url: '',
            templateUrl: serverProps.templateUrlRoot + '__States.StateListingPartial',
            controller: 'StateListingController'
        })
        .state('states.clientListing', {
            url: '/{stateAbbr}',
            templateUrl: serverProps.templateUrlRoot + '__States.ClientListingPartial',
            controller: 'ClientListingController'
        })
        .state('client', {
            abstract: false,
            url: urlRoot + '/{stateAbbr}/{clientName}?codeArchiveDate',
            templateUrl: serverProps.templateUrlRoot + '__ClientWrapperPartial',
            controller: 'ClientWrapperController',
            resolve: {
                client: ['mccSharedApi', '$stateParams', 'mccHelpers',
                    function (mccSharedApi, $stateParams, mccHelpers) {
                        return mccSharedApi.getClients({'stateAbbr' : mccHelpers.UrlDecodeComponent($stateParams.stateAbbr), 'clientName' : mccHelpers.UrlDecodeComponent($stateParams.clientName)});
                    }],
                clientRootToc: ['mccSharedApi', '$stateParams', 'mccHelpers', 'mccApi',
                    function (mccSharedApi, $stateParams, mccHelpers, mccApi) {
                        return mccSharedApi.getClients({'stateAbbr' : mccHelpers.UrlDecodeComponent($stateParams.stateAbbr), 'clientName' : mccHelpers.UrlDecodeComponent($stateParams.clientName)}).then(function (client) {
                            return mccApi.getContentToc({ clientId: client.ClientID });
                        });
                    }],
                state: ['mccSharedApi', '$stateParams', 'mccHelpers',
                    function (mccSharedApi, $stateParams, mccHelpers) {
                        return mccSharedApi.getStates({ 'stateAbbr': mccHelpers.UrlDecodeComponent($stateParams.stateAbbr) });
                    }]
            }
        })
        .state('client.ContentType', {
            url: '/{contentTypeId}'
        })
        .state('client.ContentType.Product', {
            url: '/{productName}'
        })
        .state('client.ContentType.Product.Id', {
            url: '/?nodeId'
        });
}]);

In the Head tag of my server-side html for the app I add a base tag with a full url so it works in IE also

The @ syntax is for C# Razor but I think it's clear what the point is. Use the full Url. Trailing slash or not doesn't matter.

<base href="@Request.Url.Scheme://@Request.Url.Authority/Library" />

Let me know if there's something I left out. But I tested in pushstate and non-pushstate browsers and it works.
Philip

@taylorcode
Copy link

I think that there should be the ability to set the "base" path for both $location and $resource/$http separate from the html <base> path.

In my opinion there is a logical flaw with keying off of the "base href" value for everything, because these three components are functionally decoupled.

The base for html assets (images, fonts, etc.) shares no functional relation to the base for API endpoints, nor the URL paths in an application.

It's coincidental if the base for these three components is the same -- this only occurs if all three are on the same domain and path level.

The best place for the configuration of these providers is in config... I disagree with creating a directive to configure $location, and even more so for configuring $resource. I think it's silly to configure services in the template when they perform no direct operations on or in it.

Furthermore I don't think there is ever a case where you would want to change the base path after the config phase, and creating directives with read-only attributes to configure only causes confusion (such as, 'why doesn't <html ng-location-base-path="{{locationBase}}"> work when I change $rootScope.locationBase?)

@davidbilge
Copy link

+1

2 similar comments
@GeertJohan
Copy link

+1

@andrewferk
Copy link

+1

@petebacondarwin petebacondarwin modified the milestones: 1.5.x - migration-facilitation, Backlog Mar 23, 2015
@soluml
Copy link

soluml commented May 13, 2015

+1

6 similar comments
@jackvsworld
Copy link

+1

@ogennadi
Copy link

ogennadi commented Jun 8, 2015

+1

@janjaali
Copy link

+1

@mjrk
Copy link

mjrk commented Jul 6, 2015

+1

@rcollette
Copy link

+1

@codeofsumit
Copy link

+1

@petebacondarwin
Copy link
Member

I kind of agree with @taylorcode here: #3102 (comment).
@IgorMinar and @geddski can we reconsider splitting the configuration of "root" paths for the different components and configuring them in their respective providers instead of a directive?

@LunarDevelopment
Copy link

I'm having issues with $http get/ post etc working, is there a fix for $http requests base href?

doesn't work for this, nor does .htaccess (As I'd have to place the .htaccess in root folder)

@pietrotull
Copy link

+1

@Narretz Narretz modified the milestones: 1.5.x, 1.7.0, Backlog Apr 21, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests