问题描述:

I have been struggling with creating a system to allow articles to be retrieved and opened in a modal pop-up window. It has been implemented successfully using the Bootstrap modal, but due to some new requirements I need to convert to using the Angular UI Modal.

I think the issue is stemming from my handling of URL changes by Angular's $location.search(), but I can't pinpoint it.

Since adding the $uibModal.open() call, this infinite digest loop occurs whenever I click on an article, this launching the openModal function in my controller.

I will include my controller code and the error message I receive below. The two points of entry to the controller are near the bottom at the $rootScope.$on and $scope.$watch calls. They allow the modal to respond to changes in the URL.

The end goal is the ability to open an Angular UI modal when the URL changes, so that I can remove the URL params when the modal is dismissed.

Thanks for any help!

My controller:

(function () {

'use strict';

//Create the LinkModalController and bind it to the core app. This makes it always available.

angular

.module('app.core')

.controller('LinkModalController', LinkModalController);

LinkModalController.$inject = ['$location', '$q', '$rootScope', '$scope', '$uibModal', 'contentpartservice', 'logger'];

/* @ngInject */

function LinkModalController($location, $q, $rootScope, $scope, $uibModal, contentpartservice, logger) {

var vm = this;

/*--------------Variable Definitions--------------*/

vm.modalData = {};

vm.isModalLoading = true;

vm.selectedTab;

vm.urlHistory;

/*--------------Function Definitions--------------*/

vm.selectTab = selectTab;

vm.openModal = openModal;

/*Activate Controller*/

activate();

/*--------------Functions--------------*/

/*Announcement clicks are handled separately because the announcement data contains the full article*/

function handleAnnouncementClick(data) {

vm.modalData = data;

$("#announcementModal").modal();

return;

}

/*Set the active tab for the open modal*/

function selectTab(tab) {

vm.selectedTab = tab;

return;

}

/*Clicking an article of any content type should be funneled through this function. Eventually to be merged with handleSearchResultClick*/

function handleContentTypeClick(data) {

setUrl(data.id, data.contentType.value);

return;

}

function handleUrlParamsModalLaunch(data) {

console.log('launching modal');

/*Ensure modal is not displaying any data*/

vm.modalData = {};

vm.selectedTab = null;

/*Show modal loading screen*/

vm.isModalLoading = true;

var modalInstance = $uibModal.open({

templateUrl: 'app/modals/contentTypeModalTemplate.html',

controller: 'LinkModalController as vm',

});

/*Call the content service to return the clicked content article*/

contentpartservice.getContentItem(data.id, data.type).then(function (contentItem) {

if (contentItem) {

vm.isModalLoading = false;

vm.modalData = contentItem;

return;

} else {

closeModal("#contentPartModal").then(function () {

vm.isModalLoading = false;

logger.error('An error occurred while fetching content');

});

return;

}

}, function (error) {

closeModal("#contentPartModal").then(function () {

vm.isModalLoading = false;

logger.error('An error occurred while fetching content');

});

return;

});

}

/*Close a modal and return a promise object - This allows other code to be executed only after the modal closes*/

function closeModal(modalId) {

$(modalId).modal('hide');

var defer = $q.defer();

defer.resolve();

return defer.promise;

}

//Function to append information to the URL required to retrieve the displayed article

function setUrl(contentId, contentType) {

var urlParams = $location.search();

if (urlParams.q) {

$location.search({ q: urlParams.q, type: contentType, id: contentId });

} else {

$location.search({ type: contentType, id: contentId });

}

console.log($location.search());

return;

}

/*Route link click calls to handle different data structures*/

function openModal(data, context) {

switch (context) {

case 'urlParams':

handleUrlParamsModalLaunch(data);

break;

case 'announcement':

handleAnnouncementClick(data);

break;

case 'contentType':

handleContentTypeClick(data);

break;

default:

logger.error('An error occurred while fetching content');

}

return;

}

/*--------------Listeners--------------*/

/*Catch links click events broadcast from the $rootScope (shell.controller.js)*/

$rootScope.$on('openModal', function (event, data, context) {

vm.openModal(data, context);

return;

});

/*--------------Activate Controller--------------*/

function activate() {

/*Create a watcher to detect changes to the URL*/

$scope.$watch(function () { return $location.search() }, function () {

alert('url changed');

/*Wait for modals to render*/

var urlParams = $location.search();

if (urlParams.type && urlParams.id) {

vm.openModal(urlParams, 'urlParams');

}

/*Handle the inital page load. (Must wait until content is loaded to open modal). This code only runs once.*/

$rootScope.$on('$includeContentLoaded', function () {

alert('url changed first laod');

/*Wait for modals to render*/

var urlParams = $location.search();

if (urlParams.type && urlParams.id) {

vm.openModal(urlParams, 'urlParams');

}

});

}, true);

}

}

})();

The error message that was logged is a massive block of text, so I've pasted it into a Google Doc: https://docs.google.com/document/d/1esqZSMK4_Tiqckm-IjObqTvMGre2Ls-DWrIycvW5CKY/edit?usp=sharing

网友答案:

don't know if you have tried $locationProvider.html5Mode(true); in your app's config module. If you use jquery model to open the popup, it might have conflict between angular and jquery because jquery also watches the change on the url. I used to have similar issue like this.

相关阅读:
Top