Removendo o identificador de fragmento dos URLs do AngularJS (símbolo #)

257

É possível remover o símbolo # dos URLs angular.js?

Ainda quero poder usar o botão Voltar do navegador, etc, quando alterar a exibição e atualizar o URL com parâmetros, mas não quero o símbolo #.

O tutorial routeProvider é declarado da seguinte maneira:

angular.module('phonecat', []).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider.
  when('/phones', {templateUrl: 'partials/phone-list.html',   controller: PhoneListCtrl}).
  when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
  otherwise({redirectTo: '/phones'});
}]);

Posso editar isso para ter a mesma funcionalidade sem o #?

Tim Webster
fonte
13
hashtag nice one
BoJack Horseman
Para mim, todas as respostas aqui estão erradas. Podemos "reescrever" o URL e remover o #, mas nunca acessar diretamente a página da Web sem #. Qualquer solução real aqui ???
amdev
Aqui está a solução se você estiver usando o Angular 1.6 .
Mistalis 24/03

Respostas:

251

Sim, você deve configurar $locationProvidere definir html5Modecomo true:

angular.module('phonecat', []).
  config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {

    $routeProvider.
      when('/phones', {templateUrl: 'partials/phone-list.html',   controller: PhoneListCtrl}).
      when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
      otherwise({redirectTo: '/phones'});

    $locationProvider.html5Mode(true);

  }]);
Maxim Grach
fonte
10
Como o IE lt 10 não suporta a API do histórico html5, que foi ativada pela configuração html5Mode(true). No IE, você precisa usar #nas rotas.
Maxim Grach
10
@powtac IE lt 10meio Internet Explorer menos versão 10
Maxim Grach
6
Você pode configurá-lo para que isso recorra ao uso de # no IE? É tão simples como apenas enrolando $locationProvider.html5Mode(true);em if !(IE lt 10)?
Andy Hayden
52
Portanto, essa solução resolve remover a hashtag no URL, dado que o URL possui uma hashtag, mas não resolve como responder a solicitações que não desejam que a hashtag seja incluída em primeiro lugar. Aka, resolve blah / # / phones -> blah / phones, mas não lida diretamente com blah / phones .
12124 Luke
9
Eu precisava colocar <base href = "/" /> na minha seção index.html <head>.
Nyxz
55

Certifique-se de verificar o suporte do navegador para a API de histórico html5:

  if(window.history && window.history.pushState){
    $locationProvider.html5Mode(true);
  }
SSaidi
fonte
23
Isso pode ser mais adequado como comentário, pois não responde diretamente à pergunta.
brandonscript
31
De acordo com o guia do desenvolvedor , essa detecção é feita automaticamente:If the HTML5 History API is not supported by a browser, the $location service will fall back to using the hashbang URLs automatically
IanB
Funcionou como um encanto, e eu aprecio a verificação de métodos em vez da verificação da versão do navegador - à prova de futuro.
Shane
46

Para remover a tag Hash de uma URL bonita e também para que seu código funcione após a minificação, você precisa estruturar seu código como no exemplo abaixo:

jobApp.config(['$routeProvider','$locationProvider',
    function($routeProvider, $locationProvider) {
        $routeProvider.
            when('/', {
                templateUrl: 'views/job-list.html',
                controller: 'JobListController'
            }).
            when('/menus', {
                templateUrl: 'views/job-list.html',
                controller: 'JobListController'
            }).
            when('/menus/:id', {
                templateUrl: 'views/job-detail.html',
                controller: 'JobDetailController'
            });

         //you can include a fallback by  including .otherwise({
          //redirectTo: '/jobs'
        //});


        //check browser support
        if(window.history && window.history.pushState){
            //$locationProvider.html5Mode(true); will cause an error $location in HTML5 mode requires a  tag to be present! Unless you set baseUrl tag after head tag like so: <head> <base href="https://stackoverflow.com/">

         // to know more about setting base URL visit: https://docs.angularjs.org/error/$location/nobase

         // if you don't wish to set base URL then use this
         $locationProvider.html5Mode({
                 enabled: true,
                 requireBase: false
          });
        }
    }]);
Emeka Mbah
fonte
15
Para requireBase: false+1
whoan,
2
Olá @digitlimit, Depois de adicionar o $locationProvider.html5Modecódigo, meu código $urlRouterProvider.otherwise('/home');parou de funcionar.
Jaikrat
18

Escrevo uma regra no web.config depois de $locationProvider.html5Mode(true)configurada app.js.

Espero que ajude alguém.

  <system.webServer>
    <rewrite>
      <rules>
        <rule name="AngularJS" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

No meu index.html, adicionei isso ao <head>

<base href="/">

Não se esqueça de instalar o url rewriter para iis no servidor.

Além disso, se você usar a API da Web e o IIS, esse URL de correspondência não funcionará, pois mudará as chamadas da API. Portanto, adicione a terceira entrada (terceira linha de condição) e forneça um padrão que excluirá as chamadas dewww.yourdomain.com/api

Yagiz Ozturk
fonte
1
Como você instala o reescritor de URL para o IIS? Estou hospedando no Azure.
Prabhu
11

Se você estiver na pilha do .NET com MVC e AngularJS, é isso que você deve fazer para remover o '#' do URL:

  1. Configure seu href base na sua página _Layout: <head> <base href="https://stackoverflow.com/"> </head>

  2. Em seguida, adicione o seguinte na sua configuração angular do aplicativo: $locationProvider.html5Mode(true)

  3. Acima, o '#' será removido do URL, mas a atualização da página não funcionará, por exemplo, se você estiver na página "yoursite.com/about", o refreash fornecerá um 404. Isso ocorre porque o MVC não conhece o roteamento angular e, pelo padrão do MVC, procurará uma página do MVC para 'about' que não existe no caminho de roteamento do MVC. A solução alternativa para isso é enviar todas as solicitações de página do MVC para uma única exibição do MVC e você pode fazer isso adicionando uma rota que captura todos

url:

routes.MapRoute(
    name: "App",
    url: "{*url}",
    defaults: new {
        controller = "Home", action = "Index"
    }
);
Maksood
fonte
Qual arquivo devo adicionar as rotas.MapRoute?
Vicheanak
1
RouteConfig.cs seus sob App_Start pasta
Maksood
5

Você pode ajustar o modo html5, mas isso é funcional apenas para os links incluídos nas âncoras html da sua página e como a URL se parece na barra de endereços do navegador. Tentar solicitar uma subpágina sem a hashtag (com ou sem html5mode) de qualquer lugar fora da página resultará em um erro 404. Por exemplo, a seguinte solicitação CURL resultará em um erro de página não encontrada, independentemente do html5mode:

$ curl http://foo.bar/phones

embora o seguinte retorne a página principal / raiz:

$ curl http://foo.bar/#/phones

A razão para isso é que qualquer coisa após a hashtag ser removida antes que a solicitação chegue ao servidor. Portanto, uma solicitação de http://foo.bar/#/portfoliochegada ao servidor é solicitada http://foo.bar. O servidor responderá com uma resposta 200 OK (presumivelmente) http://foo.bare o agente / cliente processará o restante.

Portanto, nos casos em que você deseja compartilhar um URL com outras pessoas, não há opção a não ser incluir a hashtag.

chris
fonte
Não há maneira de contornar isso? Este é um grande problema.
user441521
5

Siga as duas etapas:
1. Primeiro defina o $ locationProvider.html5Mode (true) no arquivo de configuração do aplicativo.
Por exemplo -
angular.module('test', ['ui.router']) .config(function($stateProvider, $urlRouterProvider, $locationProvider) { $locationProvider.html5Mode(true); $urlRouterProvider.otherwise('/'); });

2.Segundo, defina a <base> dentro da sua página principal.
Por exemplo ->
<base href="https://stackoverflow.com/">

O serviço $ location fará o fallback automaticamente para o método de parte de hash para navegadores que não suportam a API de histórico do HTML5.

Anshul Bisht
fonte
3

Minha solução é criar .htaccess e usar o código #Sorian. Sem .htaccess falhei em remover #

RewriteEngine   On
RewriteBase     /
RewriteCond     %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond     %{REQUEST_FILENAME} !-f
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ./index.html [L]
Thomas Knápek
fonte
1

De acordo com a documentação. Você pode usar:

$locationProvider.html5Mode(true).hashPrefix('!');

NB: Se o seu navegador não suporta HTML 5. Não se preocupe: D ele tem fallback para o modo hashbang. Portanto, você não precisa verificar if(window.history && window.history.pushState){ ... }manualmente

Por exemplo: Se você clicar em: <a href="https://stackoverflow.com/other">Some URL</a>

No navegador HTML5 : angular será redirecionado automaticamente paraexample.com/other

No Navegador não HTML5 : o angular será redirecionado automaticamente paraexample.com/#!/other

Efriandika Pratama
fonte
1

Esta resposta assume que você está usando o nginx como proxy reverso e já definiu $ locationProvider.html5mode como true.

-> Para as pessoas que ainda podem estar lutando com todas as coisas legais acima.

Certamente, a solução @maxim grach funciona bem, mas para a solução de como responder a solicitações que não desejam que a hashtag seja incluída em primeiro lugar, o que pode ser feito é verificar se o php está enviando 404 e reescrever o URL. A seguir está o código para nginx,

No local php, detecte o erro 404 php e redirecione para outro local,

location ~ \.php${
  ...
  fastcgi_intercept_errors on;
  error_page 404 = /redirect/$request_uri ;
}

Em seguida, reescreva o URL no local de redirecionamento e proxy_pass os dados, é claro, coloque o URL do site no lugar do URL do meu blog. (Pedido: questione isso somente depois de tentar)

location /redirect {
  rewrite ^/redirect/(.*) /$1;
  proxy_pass http://www.techromance.com;
}

E veja a mágica.

E definitivamente funciona, pelo menos para mim.

Satys
fonte
Onde adicionar isso?
precisa saber é o seguinte
Onde adicionar o código acima? Coloque-os no arquivo de configuração principal do Nginx.
Satys 4/17
1

Iniciar a partir remover index.html tudo #a partir de <a href="#/aboutus">About Us</a>então ele deve olhar como <a href="https://stackoverflow.com/aboutus">About Us</a>.Agora na marca de cabeça de gravação index.html <base href="https://stackoverflow.com/">apenas após a última tag meta .

Agora, no seu roteamento, js injeta $locationProvidere escreve $locatonProvider.html5Mode(true); algo parecido com isto: -

app.config(function ($routeProvider, $locationProvider) {
    $routeProvider
        .when("/home", {
            templateUrl: "Templates/home.html",
            controller: "homeController"
        })
            .when("/aboutus",{templateUrl:"Templates/aboutus.html"})
            .when("/courses", {
                templateUrl: "Templates/courses.html",
                controller: "coursesController"
            })
            .when("/students", {
                templateUrl: "Templates/students.html",
                controller: "studentsController"
            })
        $locationProvider.html5Mode(true);
    });

Para mais detalhes, assista a este vídeo https://www.youtube.com/watch?v=XsRugDQaGOo

Aniket Jha
fonte
A remoção de todos os # Url ajudou porque eu estava testando-o sem remover #urls.
Optimistanoop
1

Acho que é realmente tarde para isso. Mas adicionar a configuração abaixo às importações app.module faz o trabalho:

RouterModule.forRoot(routes, { useHash: false })
Sagar Bhat
fonte
0

Etapa 1: injetar o serviço $ locationProvider no construtor da configuração do aplicativo

Etapa 2: adicione a linha de código $ locationProvider.html5Mode (true) ao construtor da configuração do aplicativo.

Etapa 3: na página do contêiner (aterrissagem, mestre ou layout), adicione a tag html, como <base href="https://stackoverflow.com/">dentro dela.

Etapa 4: remova todo o '# "da configuração de roteamento de todas as tags âncora. Por exemplo, href =" # home "torna-se href =" home "; href =" # about "torna-se herf =" about "; href =" # contact "torna-se href =" contato "

 <ul class="nav navbar-nav">
     <li><a href="home">Home</a></li>
     <li><a href="about">About us</a></li>
     <li><a href="contact">Contact us</a></li>
</ul>
Thomas.Benz
fonte
-1

Basta adicionar $locationProviderEm

.config(function ($routeProvider,$locationProvider)

e em seguida, adicione $locationProvider.hashPrefix(''); depois

.otherwise({
        redirectTo: '/'
      });

É isso aí.

Narendra Solanki
fonte