Что вызывает событие «beforeunload» в Chrome? - PullRequest
0 голосов
/ 12 января 2019

Я добавляю прослушиватель событий 'beforeunload', чтобы проверить, не загрязнена ли форма, и сообщаю моим пользователям, что переход от страницы может привести к потере несохраненных данных. Поскольку я нахожусь на Chrome, я понимаю, что мне не разрешено устанавливать пользовательское сообщение, но в основном я должен добавить прослушиватель событий, чтобы появилось сообщение по умолчанию. Сообщение действительно появляется, когда моя форма грязная, но тогда я не уверен, как ее сбросить, кроме как перезагрузить страницу. У меня вопрос: что вызывает событие beforeunload? Для меня это срабатывает только тогда, когда моя форма грязная, но так как я не настроил это, я не уверен, как отключить его, когда событие инициируется.

Я пытался удалить прослушиватель событий, когда пользователь подтверждает, что хотел бы покинуть страницу, но когда я возвращаюсь на страницу и пытаюсь перезагрузить ее, событие все равно срабатывает, даже если форма не загрязнена и даже нетронутый установлен на истину.

Это соответствующий код в контроллере.

        var unloadEvent = function (e) {
            e.returnValue = '';
        };
        window.addEventListener("beforeunload", unloadEvent);

        // For when a user hits the back button 
        $transitions.onBefore({}, function ($transition)
        {
            console.log("on before", vm.ticketForm); 
            if (vm.ticketForm && vm.ticketForm.$dirty == true) {
                var answer = confirm("Are you sure you want to leave this page? Changes you made may not be saved.")
                if (!answer) {
                    // User would like to cancel the click and remain on the page
                    $window.history.forward(); 
                    $transition.abort();
                    return false;
                }
                else {
                    // Form is dirty but user would like to leave the page
                    // Set the form to pristine
                    window.removeEventListener("beforeunload", unloadEvent);
                    vm.ticketForm.$setPristine(); 
                    vm.ticketForm.$setUntouched(); 
                }
            }
        });

        $scope.$on('$destroy', function() {
            window.removeEventListener("beforeunload", unloadEvent); 
        });

Это часть HTML

 <form name="detailVM.ticketForm">
        <table class="table table-condensed table-striped table-center">
            <tbody>
                <tr>
                    <th>Username</th>
                    <th>Worker Number</th>
                    <th></th>
                    <th>Start Time</th>
                    <th>End Time</th>
                    <th>Adjusted Start Time</th>
                    <th>Adjusted End Time</th>
                    <th></th>
                </tr>

                <tr ng-repeat="worker in detailVM.currentTicket.crew_assignment.workers" ng-if="worker.revised_start_timestamp !== null && worker.revised_end_timestamp !== null">
                    <td>{{::worker.worker_username}}</td>
                    <td>{{::worker.worker_number}}</td>
                    <td><a href="#">Edit Shift</a></td>
                    <td>{{ ::detailVM.formatTime(worker.current_start_timestamp, 'MM/DD/YYYY, h:mm:ss a') }}</td>
                    <td>{{ ::detailVM.formatTime(worker.current_end_timestamp, 'MM/DD/YYYY, h:mm:ss a') }}</td>
                    <td><input type="datetime-local" ng-model="worker.revised_start_timestamp" ng-change="detailVM.changeWorkerStartTime(worker, worker.start_timestamp)"></td>
                    <td><input type="datetime-local" ng-model="worker.revised_end_timestamp" ng-change="detailVM.changeWorkerEndTime(worker, worker.end_timestmap)"></td>
                    <td>
                        <button ng-click="detailVM.deleteWorker(worker)">
                            <span class="fa fa-trash"></span>
                        </button>
                    </td>
                </tr>
                <tr ng-if="detailVM.newWorkerFormShown">
                    <td>
                        <input type="string" ng-model="detailVM.newWorkerName"/>
                    </td>
                    <td>
                        <input type="string" ng-model="detailVM.newWorkerNumber"/>
                    </td>
                    <td>
                        <input type="datetime-local" ng-model="detailVM.newWorkerStartTimestamp"/>
                    </td>
                    <td>
                        <input type="datetime-local" ng-model="detailVM.newWorkerEndTimestamp"/>
                    </td>
                    <td>
                        <button ng-click="detailVM.addWorker()">
                            <span class="fa fa-plus addButton"></span>
                        </button>
                    </td>
                </tr>
            </tbody>
        </table>
</form>

Мне неясно, что вызывает событие, потому что оно срабатывает только иногда. Насколько я могу судить, он срабатывает только после прикосновения к форме, а затем продолжает срабатывать, даже когда прослушиватель событий удаляется, а затем снова добавляется.

1 Ответ

0 голосов
/ 12 января 2019

Я добавляю прослушиватель событий 'beforeunload', чтобы проверить, не загрязнена ли форма, и сообщаю моим пользователям, что переход со страницы может привести к ose несохраненные данные.

Один из способов сделать это - создать пользовательскую директиву для директивы form:

app.directive("confirmDirtyUnload", function($window) {
    return {
        require: "ngForm", 
        link: postLink,
    };
    function postLink(scope, elem, attrs, ngForm) {
        $window.addEventListener("beforeunload", checkDirty);
        elem.on("$destroy", function (ev) {
            $window.removeEventListener("beforeunload", checkDirty);
        });
        function checkDirty(event) {
            if (ngForm.$dirty) {
                 // Cancel the event as stated by the standard.
                 event.preventDefault();
                 // Chrome requires returnValue to be set.
                 event.returnValue = '';
            };
        }
    }
});

Использование:

<form confirm-dirty-unload name="form1">
    <input name="text1" ng.model="data.text1" />
</form>
...