Un altro aspetto legato alla gestione degli stati e del routing che ho dovuto gestire è quella legata alla gestione di ricerche paginate. Lo scenario è abbastanza semplice e comune:
- form di ricerca che lancia una ricerca server-side
- viene presentata una lista di risultati paginata
- si scorrono alcune pagine (con ricerche server-side)
- si entra nel dettaglio di uno dei risultati
- si torna indietro (back)…(boom!)
Il comportamento che mi aspetto da utente è quello di tornare alla pagina da cui sono partito. Fare questo non è stato immediato per il fatto che non avevo ben compreso il legame tra lo stato “Ui-Router” e l’URL. Fondamentalmente è un legame 1:1. Uno stato implica un URL diverso. Solo definendo una sequenza di stati è possibile sfruttare il back del browser per fare quanto descritto.
Quindi, cercando di ricostruire i passi logici che ho seguito:
- 1) si parte dal servizio: cosa si aspetta in input? Nel mio caso ipotizzando di avere una ricerca in querystring per keyword, un tipico oggetto di input può essere di questo tipo:
{
keyword: "example",
startRow: 0,
pageSize: 3,
orderBy: "PublishDate",
orderDir: "DESC"
}
- 2) Ogni ricerca differente deve ricaricare una lista di risultati che deve rimanere nella history di navigazione
- 3) quindi ogni variabile deve essere intercettata dall’URL-stato. Per far questo sono tornato sulla configurazione delle route-stati inserendo nell’URL dello stato tutte le variabili in gioco
.state('lessonSearch', {
url: '/lesson?keyword?startRow?pageSize?orderBy?orderDir',
parent: 'master.2cl',
views: {
'sidebar': {
templateUrl: 'modules/lesson/sidebar.html'
},
'main': {
templateUrl: 'modules/lesson/LessonNews.html',
controller: 'LessonNewsCtrl',
resolve: {
lessonNewsData: function (LessonService, $stateParams) {
return LessonService.search($stateParams);
}
}
}
}
})
- 4) A questo punto, ovunque possa essere lanciata una ricerca (cioè dalla form di ricerca e dalla paginazione) si procede alla transizione di stato, alla quale vanno passati i parametri necessari alla ricerca. Per assicurarsi che il cambio di stato venga registrato è preferibile inserire l’opzione di reload (altrimenti potrebbe capitare che la navigazione avanti/indietro dei pulsanti di navigazione ripropongano le stesse variabili e quindi gli stessi stati già navigati, impedendo di tracciare ogni reale cambio di stato)
// Invoke search service for paging through state transition to preserve paging history
// the state transition is forced cause the same params could be used in previous navigations
$scope.getPage = function (pager) {
$state.go('lessonSearch', LessonService.getPage(pager), { reload: true })
}
Questo è il “core” della gestione degli stati. Ovviamente c’è dell’altro legato strettamente al servizio di ricerca, come il preservare sul singleton del servizio i dati della ultima ricerca/pagina visitata. Per questo rimando al repository su github.
Un aspetto che esteticamente non mi piace è il vedere in query string tutti quei parametri di ricerca. E’ inestetico secondo me, ma non ho approfondito se si riesca a mantenere questa gestione degli stati, lasciando come URL visualizzato qualcosa di più elegante. Qualcuno c’ha provato?
Comments