Как загрузить необязательный параметр, зависящий от содержимого, в одно угловое состояние?
Я строю интерфейс, который загружает список контента. Подумайте, reddit или stackru. Как и те сайты, я хочу загружать разный контент на основе разных параметров. Например, если пользователь щелкает ссылку на метатег на элементе, этот пользователь получит список контента, разделяющего этот метатег. Или, если пользователь выполняет поиск по ключевому слову, он получает контент на основе этого поиска. У меня уже есть отдельные вызовы API для получения json на основе тега, ключевого слова поиска и маршрута по умолчанию, если пользователь просто видит, что там. У меня также есть в основном рабочий способ обработки этого в угловом формате, но у него есть проблема, и я предполагаю, что есть лучший способ справиться с этим. Теперь для кода у меня есть. То, чем я делюсь, - это настройка для работы с поведением по умолчанию или со ссылкой на метатег. Поиск должен быть легко экстраполировать из этого, но я еще не беспокоился.
Здесь у меня есть отдельные маршруты для загрузки по умолчанию и загрузки контента из мета-тега. Вы заметите, что оба маршрута имеют общий контроллер и шаблон. Также вы заметите дочернее состояние items.detail. Одна из проблем моей текущей настройки заключается в том, что мне нужно, чтобы это дочернее состояние работало независимо от того, какой параметр определил, какие данные были загружены. Он загружает модал с более подробной информацией о контенте. В настоящее время, если я загрузил данные из мета-тега, он, очевидно, не сможет разрешить items.detail из состояния 'tags'.
.state('items', {
url: '/items',
templateUrl: 'views/items.html',
controller: 'mainCtrl',
authenticate: false
}).state('items.detail', {
url: '/{id}',
templateUrl: 'views/item-detail.html',
controller: 'itemDetailCtrl',
authenticate: false
})
.state('tags', {
url: '/items/tag/{tag}',
templateUrl: 'views/items.html',
controller: 'mainCtrl',
authenticate: false
})
Вот контроллер, который обрабатывает запрос содержимого после проверки, есть ли метатег для использования или нет, и затем устанавливает этот контент в объект области.
module.exports = function ($scope, API, $stateParams) {
// load data for items
if ($stateParams.tag) {
var tag = $stateParams.tag;
API.getItemsByTag(tag)
.then(function (res) {
$scope.items = res.data;
});
} else {
API.getItems()
.then(function (res) {
$scope.items = res.data;
});
}
};
Вот как выглядят мои аби абстракции вызова API
module.exports = function (Env, $http) {
// enviroment dependent base url
var base = Env.baseUrl;
return {
getItems : function (count) {
return $http.get(base + 'items');
},
getItemsByTag : function (tag) {
return $http.get(base + 'items/tags/' + tag);
},
};
};
Что может быть лучшим подходом для изменения того, как мое основное состояние "элементы" вызывает данные на основе теговой ссылки или поиска? Могу ли я передать множество дополнительных параметров в одно состояние?
Примечание: вы заметите синтаксис с 'module.exports' вместо приложения по умолчанию. Я использую browserify для комплектации, поэтому так и есть.
2 ответа
То, как мы можем расширить это use-case
можно было наблюдать здесь, в этом поршне. Фрагмент ui-sref
определение:
<a ui-sref="items({tag:'myTagOne'})">tag: myTagOne</a>
<a ui-sref="items({tag:'myTagTwo'})">tag: myTagTwo</a>
<a ui-sref="items({tag:'myTagTwo', info: 'evenInfo'})">
tag: myTagThree and info: evenInfo</a>
tag already exists, was set on items/parent state
<a ui-sref="items.detail({id: 1})">detail: 1 </a>
<a ui-sref="items.detail({id: 2})">detail: 2 </a>
tag could be also passed into detail
<a ui-sref="items.detail({id: 1, tag: null})">detail: 1, tag null </a>
<a ui-sref="items.detail({id: 2, tag: 'tg'})">detail: 2, tag 'tg' </a>
А вот маленький state
Обзор определения. (подробнее здесь)
$stateProvider
.state('items', {
url: '/items?tag&info',
template:...
controller: ...
})
.state('items.detail', {
url: '/{id:[0-9]{1,8}}',
template: ...
controller: ...
});
Родительское состояние может определять некоторые query params
как задокументировано здесь. Они либо уже установлены, когда выбрано дочернее состояние, либо могут быть также переданы:
ui-sref="items.detail({id: 2, tag: 'tg', info : '...'})"
Хорошо, я думаю, что нашел правильное решение. В итоге я использовал параметры запроса, которые я не знал, на что способен ui-router. Мой контроллер вообще не нужно было менять. У меня все еще есть операторы if, которые проверяют параметры запроса и делают разные вызовы API, если они есть. Вот как выглядят мои маршруты. Вы заметите, что параметры запроса должны быть явно объявлены в URL-адресе состояния. Я не проверял это, но я считаю, что вы можете разделить несколько параметров запроса с помощью амперсандов, и все они должны быть необязательными.
.state('items', {
url: '/items?tag',
templateUrl: 'views/items.html',
controller: 'mainCtrl',
authenticate: false
}).state('items.detail', {
url: '/{id}',
templateUrl: 'views/item-detail.html',
controller: 'itemDetailCtrl',
authenticate: false
})
Один вопрос, который все еще остается для меня, состоит в том, могу ли я объявить параметры запроса в моем пользовательском интерфейсе. Я пока не могу заставить это работать, но моя текущая настройка работает с href. Вот так.
<a href="#/items?tag={{tag}}" class="meta-tag" ng-repeat="tag in item.tags">{{ tag }}</a>
Я не знаю, есть ли проблемы с использованием hrefs с ui-router, но я буду исследовать это.