Angular передает данные на отдельную страницу

У меня есть список элементов, отображаемых из службы, с помощью ng-repeat. Все эти элементы имеют ссылку "полная информация об элементе" (item.html). Общая страница, на которой будет отображаться дополнительная информация.

Каков наилучший способ передать данные элемента, по которому щелкнули, в item.html, чтобы отображаемая информация поступала из элемента, по которому щелкнули?

HTML выглядит следующим образом:

<div class="container" ng-app="myApp">
    <div ng-controller="ItemController">
        <div ng-repeat="item in data.details">
            <div class="wrapper">
                <h3>{{item.title}}</h3>
                <p>{{item.description}}</p>
                <a href="#myModal" class="btn" openmodal>Open modal</a>
                <a href="item.html">View full item details</a>
            </div>
        </div>
    </div>
</div>

Угловой

var myApp = angular.module('myApp', []);

myApp.factory('Data', function(){
    var Data = {};  
    Data.details = [
        {
            "id": 1,
            "title": "Item 1",
            "description": "Post 1 description - Nullam ac tellus sed mi laoreet placerat.",
            "more": "more info"
        },
        {   
            "id": 2,
            "title": "Item 2",
            "description": "Post 2 description - Cociis natoque penatibus et magnis dis parturient montes.",
            "more": "more info"

        },
        {
            "id": 3,
            "title": "Item 3",
            "description": "Post 3 description - Nullam ac tellus sed mi laoreet placerat.",
            "more": "more info"
        }
    ]
    return Data;
});

// Controller
function ItemController($scope, Data){
    $scope.data = Data;
}

заранее спасибо

ИЗМЕНИТЬ

Я создал свои маршруты, HTML-страницу для каждого маршрута, а затем использовал ng-view для отображения соответствующего контента.

Смотрите мой код ниже:

// Routes
myApp.config(function($routeProvider){
    $routeProvider
        .when('/', {
                templateUrl:"home.html"
        })
        .when('/task', {
                templateUrl:"item.html"
        })
})

// Controller
function ItemController($scope, $location, Item){
    $scope.data = Item;

    $scope.viewDetail = function(item) {
        $scope.currItem= item;
        $location.path('/item');
    }
}

Теперь index.html выглядит так:

<div class="container">
    <ng-view></ng-view>
</div>

Затем я создал отдельные файлы для своих маршрутов:

home.html

<div class="container" ng-app="myApp">
    <div ng-controller="ItemController">
        <div ng-repeat="item in item.details">
            <h3>{{item.title}}</h3>
            <a ng-click="viewDetail(item)">View full item details</a>
        </div>
    </div>
</div>

item.html

<div class="container" ng-app="myApp">
    <div ng-controller="ItemController">
        <h3>{{currItem.title}}</h3>
        <p>{{currItem.description}}</p>
    </div>
</div>

Моя ссылка (Просмотр полной информации об элементе) в home.html использует ng-click для передачи нажатого объекта "item".
Теперь я хотел бы использовать этот объект элемента в item.html console.log(item) дает мне правильный объект.

Я попытался использовать «currItem» в item.html для отображения правильных данных. Это не работает.

Не уверен, что мне здесь не хватает?


person John    schedule 19.04.2013    source источник


Ответы (2)


Это действительно сводится к тому, как вы структурируете свой веб-сайт и как вы хотите, чтобы приложение работало. У вас есть несколько вариантов, первый из которых является наиболее угловатым способом сделать это.

  1. Воспользуйтесь сервисом $route и ngView.

  2. Держите все в порядке на одной странице. Вам нужно будет заменить <a href="item.html"> чем-то вроде <span ng-click="showDetails(item)">, чтобы показать/скрыть отдельный div, содержащий содержимое item.html, которое может быть привязано к $scope.currentItem. $scope.showDetails будет выглядеть так: $scope.showDetails = function (item) { $scope.currentItem = item }, а item.html будет находиться в контейнере вида: <div ng-show="currentItem != undefined">...</div> или подобном.

  3. Сделайте запрос на новую страницу, изменив <a href="item.html"> на <a href="item.html?itemId={{item.id}}">. Это потребует ряда дополнительных запросов к серверу (не только для загрузки item.html, но и для чтения location.search и последующей загрузки данных (которые уже были у вас в предыдущем запросе) обратно на новую страницу.

ИЗМЕНИТЬ

Если вы собираетесь использовать ngView, вам придется изменить ItemController, чтобы он принимал аргумент $route, который вы затем использовали бы для проверки идентификатора элемента следующим образом:

app.controller('ItemController', function ($scope, $route) {
    // TODO load the item from some service or using ajax, here's the id:
    console.log($route.current.params.id);
});
person Langdon    schedule 19.04.2013
comment
Он также может использовать локальное хранилище (HTML5). Я думаю, если вы добавите этот, вы будете указывать всеми возможными способами. - person ŁukaszBachman; 19.04.2013
comment
@Langdon, спасибо за ответ. Я бы пошел по пути Angular. У меня есть еще несколько вопросов. Смотрите мою правку. - person John; 22.04.2013
comment
@Langdon, учитывая, что все между верхним и нижним колонтитулом необходимо заменить (то же самое для нескольких других страниц). Лучше использовать ng-view или ng-template (не уверен, в чем разница)? - person John; 23.04.2013
comment
@Patrice Да, похоже, это может помочь, если вы не хотите заменять всю страницу. Единственная проблема с ngTemplate (опять же, в зависимости от вашей реализации) заключается в том, что он не такой модульный, как ngView с отдельным файлом. - person Langdon; 23.04.2013
comment
@ Патрис Я не уверен из твоего описания. Можете ли вы настроить что-нибудь на plnkr.co, что будет воспроизводить то, что у вас есть на данный момент? Кроме того, я обнаружил ngInclude, который может вам пригодиться здесь: - person Langdon; 24.04.2013
comment
@Patrice Это то, что вы ищете: plnkr.co/edit/kBu1rHse8zWu3M4UuIS9?p=preview -- (1) каждый раз, когда ваше местоположение меняется на /item, функция вашего контроллера выполняется повторно, поэтому вы теряете $scope.currItem (2) вам нужно было передать идентификатор элемента в маршруте и ссылаться на него через параметры (3 ) все, что сказано, вы должны использовать 2 отдельных контроллера 1 для списка элементов и 1 для деталей элемента. Удачи! - person Langdon; 25.04.2013
comment
@Langdon Отлично, спасибо за демонстрацию. Каковы основные отличия/преимущества использования двух отдельных контроллеров? - person John; 25.04.2013
comment
@Langdon Пытаюсь немного почистить свой код, поэтому я создал службу (дайте мне знать, правильно ли это) для загрузки моего JSON. Я попытался повторно использовать код из вашей демонстрации, чтобы открыть страницу сведений, но по-прежнему сталкиваюсь с некоторыми проблемами: plnkr.co/edit/aW8XRaV5mAwxxjjRjld2?p=preview - person John; 25.04.2013
comment
@Patrice У вас проблема с состоянием гонки. Items.get — это асинхронный вызов, поэтому $scope.currItem определяется до загрузки $scope.items. Вам нужно переместить свою логику внутри обратного вызова. plnkr.co/edit/ni38Xsn5jYhmrFXPMksE?p=preview - person Langdon; 25.04.2013

В зависимости от того, что делает index.html, вы можете передать его как параметр. например

index.html?title={{item.title}}&id={{item.id}} 

а затем используйте javascript в index.html, чтобы получить строку запроса и проанализировать ее для отображения.

Не уверены, есть ли у вас требование реализовать это как другую страницу или вы могли бы вместо этого использовать другое представление?

Если бы его можно было реализовать как отдельное представление, там было бы несколько вариантов:

  • вы можете использовать общий сервис для передачи данных другому контроллеру и привязки его к модели нового контроллера. Подробнее об услугах смотрите по следующей ссылке. http://docs.angularjs.org/guide/dev_guide.services.creating_services

  • вы можете использовать переменную $scope, чтобы создать новую модель для выбранного элемента и использовать существующий контроллер.

person anazimok    schedule 19.04.2013