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

ngAppRoot #3102

Open
Open

Description

@geddski

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?

Activity

  1. petebacondarwin commented on Jul 1, 2013

    @petebacondarwin
    Contributor

    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
    .

  2. petebacondarwin commented on Jul 1, 2013

    @petebacondarwin
    Contributor

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

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

  3. Narretz commented on Aug 22, 2013

    @Narretz
    Contributor

    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.

  4. pholly commented on Oct 15, 2013

    @pholly
    Contributor

    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.

  5. drozzy commented on Dec 5, 2013

    @drozzy

    @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?

  6. Narretz commented on Dec 19, 2013

    @Narretz
    Contributor

    +1

  7. pholly commented on Dec 19, 2013

    @pholly
    Contributor

    @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

  8. taylorcode commented on Sep 16, 2014

    @taylorcode

    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?)

  9. davidbilge commented on Oct 13, 2014

    @davidbilge

    +1

  10. GeertJohan commented on Mar 22, 2015

    @GeertJohan

    +1

  11. andrewferk commented on Mar 23, 2015

    @andrewferk

    +1

  12. 3 remaining items

  13. jackvsworld commented on May 13, 2015

    @jackvsworld

    +1

  14. ogennadi commented on Jun 8, 2015

    @ogennadi

    +1

  15. janjaali commented on Jun 12, 2015

    @janjaali

    +1

  16. mjrk commented on Jul 6, 2015

    @mjrk

    +1

  17. rcollette commented on Jul 6, 2015

    @rcollette

    +1

  18. codeofsumit commented on Sep 8, 2015

    @codeofsumit

    +1

  19. petebacondarwin commented on Sep 8, 2015

    @petebacondarwin
    Contributor

    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?

  20. LunarDevelopment commented on Sep 14, 2015

    @LunarDevelopment

    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)
  21. pietrotull commented on Apr 8, 2016

    @pietrotull

    +1

  22. modified the milestones: 1.5.x, 1.7.0, on Apr 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions