Stop Modal from closing when AngularJS gets update to model - javascript

I have a web application that polls a server for data updates (based on a queue of tests being run on the server). I have a bootstrap-modal containing a log if a test fails. When the application receives an update from the server, any open modal is closed but the page is left with the modal screen preventing interaction.
I have tried pausing updates when a modal is opened and resuming them when it is closed, but that doesn't seem to have fixed the problem. I have also tried moving the modals for logs to sit directly under in the DOM. It seems the data changing causes the page to redraw everything inside the controller.
excerpt from index.html
<div class="row" ng-controller="testStatusController as testStatus">
Header Row (static html)
<div class="row test-table-data {{script.colorClass}}" ng-repeat="script in testStatus.scripts">
<div class="col-md-2">
<p class="align-middle"><span class="d-inline d-md-none">Name: </span><span>{{script.tcName}}</span></p>
</div>
<div class="col-md-6 align-middle">
<p><span class="d-inline d-md-none">Description: </span>{{script.description}}</p>
</div>
<div class="col col-md-2 align-middle">
<p><span class="d-inline d-md-none">Run Status: </span>{{script.status}}</p>
</div>
<div class="col col-md-2">
<p>
<span class="icon text-align-middle dripicons-wrong text-danger big" ng-if="!script.pass && script.status=='Complete'" data-toggle="modal" data-target=".{{script.tcName.slice(0,-4)}}"></span>
<span class="d-inline icon dripicons-checkmark text-success big" ng-if="script.pass"></span>
<span class="spinner-border text-primary" ng-if="script.status=='Running'"></span>
<span class="d-inline icon dripicons-clock text-primary big" ng-if="script.status=='Not Run'"></span>
</p>
</div>
<div class="modal fade {{script.tcName.slice(0,-4)}} log" ng-if="!script.pass && script.status == 'Complete'">
<div class="modal-dialog modal-lg" ng-focus="testStatus.pauseUpdates(true)" ng-blur="testStatus.pauseUpdates(false)">
<div class="modal-content log-modal">
<div class="modal-header">
<div class="modal-title text-monospace">
<h4>{{script.tcName}}</h4>
<h6>{{script.description}}</h6>
</div>
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<p class="text-monospace"><span ng-repeat="log in testStatus.getLog(script.tcName).lines track by $index">{{log.line}}<br /></span></p>
</div>
</div>
</div>
</div>
</div>
<div class="row test-table-foot">
<div class="col-md-3">
<p>Passed: <span>{{testStatus.passed()}}</span></p>
</div>
<div class="col-md-3">
<p>Failed: <span>{{testStatus.failed()}}</span></p>
</div>
<div class="col-md-3">
<p>Remaining: <span>{{testStatus.remaining()}}</span></p>
</div>
<div class="col-md-3">
<p>Total: <span>{{testStatus.total()}}</span></p>
</div>
</div>
</div>
</div>
the update Function (in main.js called every 5 seconds) Comments indicate what code was removed to help keep things brief.
testList.updateResults = function () {
if (testList.running) {
$http({url:theUrl + "?cmd=json&testRun=default",
method: "GET"
}).then(function(response){
var strRes = response.data.result;
var tmp = angular.fromJson(strRes);
// update trName if bound input not focused
testList.scripts = tmp.tc;
testList.running = false;
angular.forEach(tmp.tc, function(script, index){
if(script.status != "Complete") {
testList.running = true;
script.colorClass = "text-primary";
}
else {
if(script.pass) {
script.colorClass = "text-success";
}
else {
script.colorClass = "text-danger";
if(!(script.tcName.slice(0, -4) in testList.logs)) {
testList.getLog(script.tcName);
}
}
}
});
// update start/stop button
}, function(data){
console.log(data);
});
}
};
I would expect that AngularJS would not update sections of the DOM if the data bound to them was the same, but instead everything in the controller section is redrawn. My next instinct was to separate the logs and the status into different controllers, but I suspect I will have the same problem when a new log gets appended to the list of logs.

Related

How to bind this within js nested object iteration within a function. Jquery

again, probably a terrible title - but what I'm trying to do is to make a simple search feature on my website. You click a nav button, which updates the search bar, whi in turn triggers an onchange event to update the current appended list.
function update() {
var list = $("#comic__modern-list");
list.empty();
$.each(Object.keys(comics), function() {
var currentObject = comics[this];
var filter = comics[this].type;
var publisher = comics[this].publisher;
if (search == "") {
if(filter == "modern") {
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
} else if (search == publisher) {
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
});
}
The current list is generated by this, which works fine:
$.each(Object.keys(comics), function() {
var currentObject = comics[this];
var currentObject2 = comics[this].type;
console.log(currentObject2);
if (search == "") {
if(currentObject2 == "modern") {
var list = $("#comic__modern-list");
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
}
});
From what I can gather, this has to do with the keyword "this" no longer meaning what it did when it was outside of the function, so I'm assuming the fix will be to do with bind(), but I can't make heads nor tails of it.
p.s, if there's an easier/simpler way to set up a search system, please enlighten me!

How can I make sure slidetoggle only fires when the same element is clicked

I got three blocks, when a block is clicked a div slides open using slideToggle. When the same block is clicked the div closes, this works as it should, but if the second block is clicked the data that belongs to the second block is loaded, but it instantly slides back up (closes).
How can I make sure that it only closes when the same block is clicked twice and just switches data / stays open when another block is clicked?
My html:
<div class="col-md-4 col-sm-6 vk-clear-padding handmouse haven">
<div class="vk-iconbox vk-iconbox-background text-center" style="background-color: #ececec;">
<div class="iconbox-content vk-section-style-5">
<h2 class="vk-heading text-uppercase" aria-label="01">
<span>Haven & Industrie</span>
</h2>
</div>
</div>
</div>
<div class="col-md-4 col-sm-6 vk-clear-padding handmouse openbaar">
<div class="vk-iconbox vk-iconbox-background vk-iconbox-striped text-center" style="background-color: #faf5f5;">
<div class="iconbox-content vk-section-style-5">
<h2 class="vk-heading text-uppercase" aria-label="02">
<span>Openbare Ruimte</span>
</h2>
</div>
</div>
</div>
<div class="col-md-4 col-sm-6 vk-clear-padding handmouse landmeten">
<div class="vk-iconbox vk-iconbox-background text-center" style="background-color: #ececec;">
<div class="iconbox-content vk-section-style-5">
<h2 class="vk-heading text-uppercase" aria-label="03">
<span>Landmeten</span>
</h2>
</div>
</div>
</div>
<div class="vk-what-we-do-section vk-section vk-section-style-2 vk-section-style-3 tabwrapper">
</div>
My jQuery:
$('.handmouse').on('click', function(e){
var alias = $(this).attr("data-attribute");
$.post("ajax/blokken.php", {
dienstnaam : alias
}, function(data) {
$(".tabwrapper").html(data);
MasonryItem.init();
});
$('.tabwrapper').slideToggle();
$('html, body').animate({
scrollTop: $(".tabwrapper").offset().top
}, 2000);
});
The three blocks all can be identified by their last classes (haven, openbaar, landmeten).

Why does my view not update when changing scope variable?

Navbar (main.html):
<nav class="navbar navbar-dark bg-primary">
<button class="navbar-toggler hidden-sm-up" type="button" data-toggle="collapse" data-target="#collapseEx2">
<i class="fa fa-bars"></i>
</button>
<div class="container" ng-controller="UpComingGamesCtrl">
<div class="collapse navbar-toggleable-xs" id="collapseEx2">
<a class="navbar-brand" href="#/">VideoGame Releases</a>
<form ng-submit="searchGame()">
<input type="text" id="form1" class="form-control" ng-model="gameToSearch">
</form>
</div>
</div>
</nav>
Controller:
...
$scope.games = [];
$scope.searchGame = function () {
if ($scope.gameToSearch) {
console.log('entered with text');
getUpcomingGames.getGame($scope.gameToSearch).get({}, function (data) {
$scope.games = data.results;
});
}
}
upcoming_games_template.html:
<div class="row" ng-repeat="games in games | chunkBy:3">
<div class="col-md-4" ng-repeat="game in games">
<div class="card">
<div class="view overlay hm-white-slight card-image">
<img src="{{game.image.screen_url}}" class="img-fluid" alt="">
<a href="#/">
<div class="mask waves-effect waves-light"></div>
</a>
</div>
<div class="card-block">
<h4 class="card-title">{{game.name}}</h4>
<p class="card-text">{{(game.original_release_date | limitTo: 10) || getFutureReleaseDate(game) }}</p>
Read more
</div>
</div>
</div>
</div>
I am trying to create a search function on my navbar in my main.html file and when the user presses the enter key, I get the info from an external API using that search and update the upcoming_games template. Now, I know I enter the function "searchGame" because it logs to console and I know the data I get back is good. But when i try to change the variable "$scope.games = data.results;", the view does not update.
Now if I create the same search bar form inside the upcoming_games_template.html it works perfectly.
Why does this happen ? I'm declaring the controller in my main.html file, so it should work the same, right ?
I also don't think I need the $scope.$apply() in this situation.
Thank you.
Probably you're using two different controllers, so you're filling the $scope.games variable of a controller while you would fill the $scope.games variable of the other controller. If you provide a jsfiddle it could be simpler. If you want a fast solution you should try to use a $rootScope.games variable and repeat over the same rootscope variable :
<div class="row" ng-repeat="games in $root.games | chunkBy:3">
<!-- Content -->
</div>
This is not the better solution but it should works.

How to call $scope.closePopup on click in angular js?

I created the popup when I am trying to call action on click for close pop up icon no change is shown.
In index.html in bottom there is code for pop up, this will be shown when user will click on change zip code link.
<!-- Pop up div -->
<div class="popup" ng-show="myModal" ng-controller="utilityCtrl">
<!-- Modal content -->
<div class="popup-content">
<span class="close" ng-click="closePopup">×</span>
<div class="dynamicContect" id="dynamicContect"> Loading ...
</div>
</div>
</div>
<!-- html of change zip code -->
<div class="hidden" id="updateZipContent">
<div class="zipContent">
<div class="padding-bt-2">Please enter new zip code</div>
<div class="row">
<div class="text-left col-md-6 padding-bt-2">
<input ng-model="zipCode" type="text" class="form-control" maxlength="5" data-required="true" number-only>
</div>
<div class="text-left col-md-4">
<button class="btn btn-primary form-control">Update</button>
</div>
</div>
</div>
</div>
Change zip code action is written in autoQuotectrl.js
$scope.changeZipCode = function()
{
$rootScope.myModal = true;
var firstDivContent = document.getElementById('updateZipContent');
var secondDivContent = document.getElementById('dynamicContect');
secondDivContent.innerHTML = firstDivContent.innerHTML;
}
To keep other action separate I wrote new controller utilityCtrl.js.
Here I wrote action for hide this popup .
$scope.closePopup = function ()
{
console.log('here in utility');
$rootScope.myModal = false;
document.getElementById('dynamicContect').innerHTML = "";
}
But nothing is working, please help me to understand what I am missing here.
It seems $rootScope.myModal is not accessible in utilityCtrl
You don't invoke function closePopup in template.
See example on plunker.
<div class="popup" ng-show="myModal" ng-controller="utilityCtrl">
<!-- Modal content -->
<div class="popup-content">
<span class="close" ng-click="closePopup()">×</span>
<div class="dynamicContect" id="dynamicContect"> Loading ...
</div>
</div>
</div>
they are in two controller,so the $scope is diferent ,you can use $rootScope.$broadcast and $scope.$on

Closing a modal by clicking outside of the modal

I have a modal window build with CSS. The modal can be closed by clicking outside of it.
My solution to open the modal works, closing the modal works too, when the event listeners are added to the page separately. However, they don't work together. When both the listeners are added to the page, the modal won't open.
How can I make them to work together?
HTML
<a href="#openModal" id="modal-window" class="event test">
<div class="shorten-long-text test">
</div>
</a>
<div id="openModal" class="modalDialog Dialog1">
<div class="myModal">
<div class="modal-header">
</div>
<div class="modal-body row">
<div class="col-xs-6" >
</div>
</div>
<div class="modal-footer uppercase color-main">
</div>
</div>
</div>
JS
$(window).click(function(ev) {
if($(ev.target).attr('class') != ".Dialog1" ) {
$(".Dialog1").removeClass('isOpen');
$(".Dialog1").addClass('isClosed');
}
});
$(".test").click(function() {
$(".Dialog1").removeClass('isClosed');
$(".Dialog1").addClass('isOpen');
});
Use toggleClass()
html:
<div id="openModal" class="modalDialog isClosed Dialog1">
js:
$(window).click(function(ev) {
if(!$(ev.target).is('.Dialog1,.test') $(".Dialog1").toggleClass('isClosed isOpen');
}
});
$(".test").click(function() {
$(".Dialog1").toggleClass('isClosed isOpen');
});

Categories

Resources