Ich habe ein Angular SPA, das eine Vielzahl von Empfehlungslisten und eine Google-Karte mit Standorten enthält, die auf verschiedenen Ausschnitten einiger Restaurantdaten basieren (siehe m.amsterdamfoodie.nl ). Ich möchte, dass jede dieser Listen eine eigene URL hat. Damit Google die verschiedenen Listen durchsuchen kann, verwende ich <a>
-Tags für die offcanvas-Navigation.
Derzeit bewirkt das <a>
-Tag eine Aktualisierung der Ansicht, die bei der Karte sehr auffällig ist.
ng-click
und $event.preventDefault()
verhindern (siehe Code-Ausschnitte unten), aber dann muss ich ein Mittel implementieren, um die Browser-URL zu aktualisieren.$state
oder den Browser history.pushstate
des Browsers versuche, löse ich am Ende Zustandsänderungen aus und die Ansicht wird aktualisiert ...!Meine Frage ist daher wie kann ich ein Modell und die URL aktualisieren, ohne die Ansicht zu aktualisieren? (Siehe auch Angular/UI-Router - Wie kann ich die URL aktualisieren, ohne alles zu aktualisieren? )
Ich habe mit vielen Ansätzen experimentiert und habe derzeit dieses HTML
<a href="criteria/price/1" class="btn btn-default" ng-click="main.action($event)">Budget</a>
Im Controller:
this.action = ($event) ->
$event.preventDefault()
params = $event.target.href.match(/criteria\/(.*)\/(.*)$/)
# seems to cause a view refresh
# history.pushState({}, "page 2", "criteria/"+params[1]+"/"+params[2]);
# seems to cause a view refresh
# $state.transitionTo 'criteria', {criteria:params[1], q:params[2]}, {inherit:false}
updateModel(...)
Und ich glaube, dass ich den $stateProvider
-Code auslöst:
angular.module 'afmnewApp'
.config ($stateProvider) ->
$stateProvider
.state 'main',
url: '/'
templateUrl: 'app/main/main.html'
controller: 'MainCtrl'
controllerAs: 'main'
.state 'criteria',
url: '/criteria/:criteria/:q'
templateUrl: 'app/main/main.html'
controller: 'MainCtrl'
controllerAs: 'main'
Ein möglicher Hinweis ist der folgende Code, wenn ich z. http://afmnew.herokuapp.com/criteria/cuisine/italian dann wird die Ansicht aktualisiert, während Sie navigieren, wohingegen beim Laden von http://afmnew.herokuapp.com/ dort sind keine Aktualisierungen, jedoch keine URL-Aktualisierungen. Ich verstehe nicht, warum das überhaupt passiert.
Basierend auf unseren vorherigen Diskussionen möchte ich Ihnen eine Vorstellung davon geben, wie Sie hier UI-Router
verwenden. Ich glaube, ich verstehe Ihre Herausforderung richtig ... Es gibt ein funktionierendes Beispiel . Wenn dies nicht vollständig passt, nehmen Sie es als Inspiration
HAFTUNGSAUSSCHLUSS: Mit einem Plunker konnte ich dies nicht erreichen: http://m.amsterdamfoodie.nl/ , aber das Prinzip sollte in Beispiel Ähnlichem stehen
Es gibt also eine Zustandsdefinition (wir haben nur zwei Zustände)}
$stateProvider
.state('main', {
url: '/',
views: {
'@' : {
templateUrl: 'tpl.layout.html',
controller: 'MainCtrl',
},
'[email protected]' : { templateUrl: 'tpl.right.html',},
'[email protected]' : {
templateUrl: 'tpl.map.html',
controller: 'MapCtrl',
},
'[email protected]' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
},
},
})
.state('main.criteria', {
url: '^/criteria/:criteria/:value',
views: {
'map' : {
templateUrl: 'tpl.map.html',
controller: 'MapCtrl',
},
'list' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
},
},
})
}];
Dies wäre unser Haupt tpl.layout.html
<div>
<section class="main">
<section class="map">
<div ui-view="map"></div>
</section>
<section class="list">
<div ui-view="list"></div>
</section>
</section>
<section class="right">
<div ui-view="right"></div>
</section>
</div>
Wie wir sehen können, zielt der Hauptzustand auf diese verschachtelten Ansichten des Hauptzustands: 'viewName @ main', z. '[email protected]'
Auch die Unteransicht main.criteria
fügt sich in layout - Ansichten ein.
Seine URL beginnt mit einem Zeichen ^ (url : '^/criteria/:criteria/:value'
), das einen /
-Schrägstrich für main und keinen doppelten Schrägstrich für untergeordnetes Element erlaubt
Und es gibt auch Controller, die hier etwas naiv sind, aber sie sollten zeigen, dass im Hintergrund echte Datenlast (basierend auf Kriterien) sein könnte.
Das Wichtigste dabei ist, dass die PARENT MainCtrl
den $scope.Model = {}
erstellt. Diese Eigenschaft wird (dank der Vererbung) zwischen Eltern und Kindern geteilt. Deshalb funktioniert das alles:
app.controller('MainCtrl', function($scope)
{
$scope.Model = {};
$scope.Model.data = ['Rest1', 'Rest2', 'Rest3', 'Rest4', 'Rest5'];
$scope.Model.randOrd = function (){ return (Math.round(Math.random())-0.5); };
})
.controller('ListCtrl', function($scope, $stateParams)
{
$scope.Model.list = []
$scope.Model.data
.sort( $scope.Model.randOrd )
.forEach(function(i) {$scope.Model.list.Push(i + " - " + $stateParams.value || "root")})
$scope.Model.selected = $scope.Model.list[0];
$scope.Model.select = function(index){
$scope.Model.selected = $scope.Model.list[index];
}
})
Hier erfahren Sie, wie wir die von UI-Router bereitgestellten Funktionen nutzen können:
Überprüfen Sie den obigen Auszug hier , in das Arbeitsbeispiel
Erweitern: neuer Plunker hier
Wenn die Kartenansicht nicht wiederhergestellt werden soll, können Sie diese Option aus dem untergeordneten Status def weglassen:
.state('main.criteria', {
url: '^/criteria/:criteria/:value',
views: {
// 'map' : {
// templateUrl: 'tpl.map.html',
// controller: 'MapCtrl',
//},
'list' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
},
},
})
Jetzt werden in unserer Kartenansicht lediglich Änderungen im Modell empfangen (können betrachtet werden), aber Ansicht und Controller werden nicht erneut gerendert
Es gibt auch einen anderen Plunker http://plnkr.co/edit/y0GzHv?p=preview , der die controllerAs
verwendet.
.state('main', {
url: '/',
views: {
'@' : {
templateUrl: 'tpl.layout.html',
controller: 'MainCtrl',
controllerAs: 'main', // here
},
...
},
})
.state('main.criteria', {
url: '^/criteria/:criteria/:value',
views: {
'list' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
controllerAs: 'list', // here
},
},
})
und das könnte so verwendet werden:
<h4>{{main.hello()}}</h4>
<h4>{{list.hello()}}</h4>
Der letzte Plunker ist hier
Dies ist ein Beispiel für den Weg, wenn ich es richtig verstanden habe:
$state.go('my.state', {id:data.id}, {notify:false, reload:false});
//And to remove the id from the url:
$state.go('my.state', {id:undefined}, {notify:false, reload:false});
Von Benutzer l-liava-l in der Ausgabe https://github.com/angular-ui/ui-router/issues/64
Sie können die $state
-API hier überprüfen: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state . $ State
sie können die Bereichsvererbung verwenden, um die URL ohne Aktualisierung der Ansicht zu aktualisieren
$stateProvider
.state('itemList', {
url: '/itemlist',
templateUrl: 'Scripts/app/item/ItemListTemplate.html',
controller: 'ItemListController as itemList'
//abstract: true //abstract maybe?
}).state('itemList.itemDetail', {
url: '/:itemName/:itemID',
templateUrl: 'Scripts/app/item/ItemDetailTemplate.html',
controller: 'ItemDetailController as itemDetail',
resolve: {
'CurrentItemID': ['$stateParams',function ($stateParams) {
return $stateParams['itemID'];
}]
}
})
wenn sich die untergeordnete Ansicht in der übergeordneten Ansicht befindet, teilen sich beide Controller denselben Bereich. Sie können also eine Dummy-Ansicht (oder eine erforderliche Ui-Ansicht) in die übergeordnete Ansicht einfügen, die von der untergeordneten Ansicht gefüllt wird.
und füge ein
$scope.loadChildData = function(itemID){..blabla..};
funktion in der übergeordneten Steuerung, die bei der Controller-Belastung von der untergeordneten Steuerung aufgerufen wird. Wenn also ein Benutzer klickt
<a ui-sref="childState({itemID: 12})">bla</a>
nur untergeordnete Controller und untergeordnete Ansichten werden aktualisiert. Dann können Sie die Parent-Scope-Funktion mit den erforderlichen Parametern aufrufen.
Die kurze Antwort endete mit do not die Karte in eine sich ändernde Ansicht. Die akzeptierte Antwort enthält viel detailliertere Informationen zum Strukturieren einer Seite mit Unteransichten. Der Schlüsselpunkt ist jedoch nicht, die Karte in die Ansicht aufzunehmen, sondern ihr Verhalten mit einer Ansicht zu verknüpfen, die sich ändert, und einen Controller zu verwenden Aktualisieren Sie die Marktsymbole.