AngularJS и nodeJs Express: маршруты и обновление

Мое приложение "работает" нормально, но когда я нажимаю F5 в браузере, появляется проблема.

Мое приложение организовано следующим образом:

nodeJs + экспресс, в экспрессе:

app.use(express.static('public'));
app.use( app.router );
app.use(function(req, res) {
    res.sendfile(__dirname + '/public/index.html');
});

мои угловые маршруты:

app.config(function($locationProvider, $routeProvider) {
    $locationProvider
        .html5Mode(true)
        .hashPrefix('!');
    $routeProvider
        .when('/', { templateUrl: '/page/home.html'})
        .when('/activate/:token', { templateUrl: '/page/activate.html'})
        .otherwise({ redirectTo: '/' });
});

и все работает нормально, пока я не обновлю страницу, если я нахожусь на локальном хосте: 1234/activate/999, страница хорошо обновляется, но в консоли появляется эта ошибка

Error: Template must have exactly one root element. was:<!DOCTYPE html>
<html ng-app=app xmlns="http://www.w3.org/1999/html">
<head>
    <title>title</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    bla
    bla
    bla

весь мой index.html! какие могут быть проблемы? есть решения?
edit:
мой дом:

<div>
    <section id="feature_slider" class="">
        //...
    </section>

    <div id="showcase">
        //...
    </div>


    <script type="text/javascript" src="/js/index-slider.js"></script>
</div>

ми активировать:

<div>
    test
</div>

мой index.html

<!DOCTYPE html>
<html ng-app=app xmlns="http://www.w3.org/1999/html">
<head>
    <title>tite</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Styles -->
    <link href="/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/bootstrap-responsive.min.css" rel="stylesheet">
    <link href="/css/bootstrap-overrides.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="/css/theme.css">
    <link rel="stylesheet" href="/css/index.css" type="text/css" media="screen" />


    <link rel="stylesheet" type="text/css" href="/css/lib/animate.css" media="screen, projection">
    <link rel="stylesheet" href="/css/sign-in.css" type="text/css" media="screen" />
    <link rel="stylesheet" href="/css/myCss.css" type="text/css"/>


</head>
<body class="pull_top">
    <navbar>
    //...
    </navbar>

    <ng-view> Loading...
    </ng-view>
    <!-- starts footer -->
    <footer id="footer">
       //...
    </footer>



     <!--Preload-->
    <script src="/js/jquery-1.10.1.min.js"></script>
    <!-- Scripts -->
    <script src="/js/bootstrap.min.js"></script>
    <script src="/js/theme.js"></script>



    <!--Angular-->
    <script type="text/javascript" src="/js/angular.min.js"></script>
    <!--<script type="text/javascript" src="/js/angular-ui.min.js"></script>-->
    <script type="text/javascript" src="/js/ui-bootstrap-0.5.0.min.js"></script>
    <script type="text/javascript" src="/angular/app.js"></script>

    <!--Angular Controller-->
    <script type="text/javascript" src="/angular/login/loginController.js"></script>
    <script type="text/javascript" src="/angular/menuNavBar/menuController.js"></script>
    <script type="text/javascript" src="/angular/login/logOutController.js"></script>
    <script type="text/javascript" src="/angular/login/registerController.js"></script>

    <!--Angular Services-->
    <script type="text/javascript" src="/angular/alertBox/messageBoxController.js"></script>

    <!--Router-->
    <script type="text/javascript" src="/angular/router/router.js"></script>




</body>


person justBorn    schedule 14.08.2013    source источник
comment
Шаблоны должны иметь один и только один корневой элемент для привязки контроллера — может помочь, если вы покажете нам активировать.html и индекс.html. Вы где-нибудь использовали директиву ng-view?   -  person Ian Haggerty    schedule 14.08.2013
comment
вы правы, я редактирую свой вопрос   -  person justBorn    schedule 15.08.2013


Ответы (2)


Это проблема, обычно возникающая при использовании универсального маршрута, который возвращает index.html (что вам нужно сделать при использовании режима Angular html5).

Я не знаю, как выглядит ваша структура общих папок, но ваш Angular делает запрос для активации.html, который не соответствует его фактическому местоположению (как обслуживается Express). Это может быть связано с тем, что в вашем templateUrl есть косая черта:

{ templateUrl: '/page/activate.html'})

но это зависит от того, как выглядит ваша общая папка. «/page/activate.html» предполагает, что папка «page» находится в корне вашей общей папки. Если это не так, то это ваши проблемы. Вы должны иметь:

{ templateUrl: 'path/relative/to/public/folder/page/activate.html'})

который, я предполагаю, в вашем случае будет примерно таким:

{ templateUrl: 'views/page/activate.html'})

(Маловероятно, что в корне папки public/ будет папка с именем «page».)

Ваше экспресс-промежуточное ПО пытается обработать запрос на

http://localhost:1234/page/activate.html

но ничто не справляется с этим, поэтому ваш универсальный маршрут просто возвращает index.html, который имеет несколько корневых элементов, что приводит к тому, что Angular выдает ошибку. Angular ожидал активировать.html, но вместо этого получил index.html.

Это произойдет всякий раз, когда клиент делает запрос, который Express не может обработать, потому что универсальный маршрутизатор вернет index.html. Вы можете запустить свой браузер в бесконечный цикл, поскольку он постоянно загружает index.html, который загружает Angular, который (ошибочно) загружает index.html, который загружает Angular и т. д.

Посмотрите на запрос, который ваш браузер отправляет для активации.html, и сделайте так, чтобы он соответствовал фактическому местоположению (которое обслуживается Express) активировать.html.

person jdobry    schedule 15.08.2013
comment
Привет! Спасибо за ответ! извините, я сейчас не дома, у меня вопрос, если запрос был неправильным, он не должен отображаться правильно? Правильно?? потому что консоль печатает ошибку, но страница отображается правильно! Я узнаю ошибку случайно! - person justBorn; 22.08.2013

Попробуйте использовать укажите templateUrl с абсолютным путем из root представлений.

Например, предположим, что вы настроили и views находится в папке public

app.set('views', __dirname + '/public');

затем измените путь к шаблону на

/public/page/home.html
person zs2020    schedule 14.08.2013
comment
разве это не так, он отвечает мне всем index.html, вместо этого я включаю только home.html и активировать.html! - person justBorn; 15.08.2013
comment
@justBorn Очевидно, вы не опубликовали все шаблоны до того, как я ответил на ваши вопросы. Можете ли вы опубликовать index.html? И я вижу много неправильного синтаксиса, такого как ng-app=app, приложение должно быть заключено в кавычки. Убедитесь, что вы исправили все эти глупые ошибки, чтобы избавиться от ложных тревог. - person zs2020; 15.08.2013
comment
извините, но я учусь, не могли бы вы помочь мне сказать, какая ошибка? Тогда ng-app=app должно быть ng-app=app? Благодарность - person justBorn; 15.08.2013
comment
Я думаю, что лучше всего также использовать ng-view в качестве атрибута: ‹div ng-view› - person Ian Haggerty; 15.08.2013