user2128 user2128 - 3 months ago 20
AngularJS Question

implement back button functionality using $state

My application has multiple states.
enter image description here

The workflow is such that from the landing page I go into Alert view page that has list of alerts in a tabular format. From that list I select an alert which takes the me into the Alert Detail page, that gives detailed information of that particular alert. Within that alert Detail state, there are subviews in the form of navigation tabs that displays various aspect of that alert when clicked on the particular tab.

AlertView.config.js:

$stateProvider.state({
name: "alert-view",
parent: "root",
url: "/alert/view?id&name&criteria&start&end&targets&sort",
data: {
pageTitle: "Alert View"
},
views: {
"main.content@": {
templateUrl: "components/alerts/alert-view/alert-view.html",
controller: "AlertViewsController",
controllerAs: "vm"
}
}


Alert Detail Page.config.js

$stateProvider.state({
name: "alert-details",
parent: "root",
abstract: true,
url: "/alert/details/:id",
params: {
// this will make both links /alert/details & /alert/details/ work
id: {squash: true, value: null}
},
data: {
pageTitle: "Alert Details"
},
views: {
"main.content@": {
templateUrl: "components/alerts/alert-details/alert-details.html",
controller: "AlertDetailsController as vm"
},
"alertViewDetail@alert-details": {
templateUrl: "components/alerts/alert-details/overview/overview.html",
controller: "AlertDetailsOverviewController as vm"
//@todo parent/child controller.
}
},
}).state({
name: "alert-details.overview",
parent: "alert-details",
url: "/overview",
params: {
// this will make both links /alert/details & /alert/details/ work
id: {squash: true, value: null}
},
data: {
pageTitle: "Alert Details"
},
views: {
"alertViewDetail@alert-details": {
templateUrl: "components/alerts/alert-details/overview/overview.html",
controller: "AlertDetailsOverviewController as vm",
controllerAs: "vm"
}
}
}).state({
name: "alert-details.history",
parent: "alert-details",
url: "/history",
params: {
// this will make both links /alert/details & /alert/details/ work
id: {squash: true, value: null}
},
data: {
pageTitle: "Alert Details"
},
views: {
"alertViewDetail@alert-details": {
templateUrl: "components/alerts/alert-details/history/history.html",
controller: "AlertDetailsHistoryController",
controllerAs: "vm"
}
}
}).state({
name: "alert-details.trigger",
parent: "alert-details",
url: "/trigger-events",
params: {
// this will make both links /alert/details & /alert/details/ work
id: {squash: true, value: null}
},
data: {
pageTitle: "Trigger Events"
},
views: {
"alertViewDetail@alert-details": {
templateUrl: "components/alerts/alert-details/trigger-events/trigger-events.html",
controller: "AlertDetailsTriggerEventsController",
controllerAs: "vm"
}
}
}).state({
name: "alert-details.all-fields",
parent: "alert-details",
url: "/all-fields",
params: {
// this will make both links /alert/details & /alert/details/ work
id: {squash: true, value: null}
},
data: {
pageTitle: "All Alert Fields"
},
views: {
"alertViewDetail@alert-details": {
templateUrl: "components/alerts/alert-details/all-fields/all-fields.html",
controller: "AlertDetailsAllAlertFieldsController",
controllerAs: "vm"
}
}
});


alertDetail.html

<button ng-click="vm.goBack()" class="btn btn-default"><i class="icon icon-long-arrow-left"></i><span translate>Back</span></button>


alertDetail.controller.js

vm.goBack = function () {
history.back();
};


My aim is to implement the back button in the alert detail page such that , no matter in whichever subview I am, if clicked on the back button, it directs me to Alert View Page. I tried using history.back() to do so. But it traverses through all the previous state rather than routing to Alert View page directly.
How should I utilise the state information of the Alert View page and Alert Detail page, in order to implement the required scenario. Please help.

Answer

To solve the problem of saving the current URL and use it later, I created a service that would take in the the query string of the URL as a single object. Then when i need to go to that URL in that same state, I would use that query string object and pass it as a parameter on $state. so vm.goBack function would look like this:

vm.goBack = function () {
            $state.go("alert-view", {name: alertHistory.getHistory().name, criteria: alertHistory.getHistory().criteria, sort: alertHistory.getHistory().sort});
        };

the service that i created was: (function () { "use strict";

angular
    .module("app.alerts")
    .service("alertHistory", alertHistory);

alertHistory.$inject = [
    "$location",
    "logger"];



function alertHistory ($location, logger) {
    var historyURL = {
        init: null,
        saveURL: saveURL,
        getHistory: getHistory
    };
    return historyURL;

    function saveURL (urlObj) {
        historyURL.currentURL = urlObj;
    }
    function getHistory () {
        return historyURL.currentURL;
    }
}

})();

in controller I obtain the query string using $location.search() :

alertHistory.saveURL($location.search());

This might not be the ideal solution. But it works for what i need :) Any suggestions are welcome!