AngularJS' $interval.cancel not working - angularjs

As stated in the title,
every time I try to use $interval.cancel to cancel an existing interval, it doesn't work.
window.recordedAudio = undefined;
var isRecordingComplete = $interval(function(){
console.log(window.recordedAudio);
if (window.recordedAudio!=undefined) $timeout.cancel(isRecordingComplete);
},100);
$timeout(function(){
window.recordedAudio = "abc";
},2000);
In fact, when window.recordedAudio!= undefined (window.recordedAudio is set to "abc" after 2000ms), the $interval keeps looping and at the same time the
console.log(window.recordedAudio)
keeps being printed (+- 10 times undefined and finally abc but it keeps printing abc rather than just stop).

You are mixing $interval and $timeout.cancel.

Related

changing state before next keydown in react

I am creating a game that when your health goes below 0, on a keydown it prints in a div:
"Game_over_:(_click_to_continue" letter by letter. I was getting a bug where the letters would print out multiple times like ggggaaammmeee ooovvveerr.
I set up a conditional statement where if the state gameOver is 0 and after a keydown event, then it activates the setInterval, else it does not. That solved the problem to some extent, however, the state sometimes changes a second late, and after setting up console.log(this.state.gameOver), it sometimes prints 0 twice before this.state.gameOver actually changes to 1. Other times it works just fine.
if (this.state.gameOver===0){
console.log(this.state.gameOver)
var s1="Game_Over\n:(\nClick_to_continue..."
var v1 =0
var b = document.getElementById("redButton")
var arr1 = setInterval(function(){
if(v1===0){b.innerText=""};b.innerText= b.innerText+s1[v1];v1+=1;
if(v1==s1.length){clearInterval(arr1)}}, 100)
this.setState({gameOver:1})
}
It's still sometimes printing Ggaammee Ovveerr.
So all I had to do was set up a conditional statement that depends on whether a variable is true or false. Once the setInterval function is triggered, the variable changes to false so that more keydowns wont cause multiple calls to setInterval.
var check;
if (check!==false){
check=false;
var arr1 = setInterval(function(){
if(v1===0){b.innerText=""};
b.innerText= b.innerText+s1[v1];v1+=1;
if(v1==s1.length){clearInterval(arr1)}}, 100)}
Once I click the screen with the mouse:
check=true;

Converting HH:MM String into Time Object

In my Ionic AngularJS Project, I have a string called startingTime set as 08:30
I will have a ng-repeat loop which will then make a series of items with an increasing time.
For example , the first item in the list will have 08:30, second item in the list 09:00 etc ( the increment will depend on another variable so its not 30mins every loop )
The problem is I cant seem to turn the string into a Time Object and i get null displayed most of the time if i try the following
$scope.newStartTime = moment(startTime).format('HH-MM');
OR
$scope.newStartTime = var date = new Date(startTime);
So my 2 main questions are.
How do i convert a string "08:30" into a time object ?
After its a time object, how can i make a loop so the time increases by minutes after every loop ?
Thank you.
This method work for me, that transform your startingTime into a MomentObject :
var startingTime = "8:30";
var date = moment(startingTime, "HHmm");`
console.log(date);
plunker demo
For create your timer you can make something like that :
$scope.timer = moment(startingTime,"HHmm");
$scope.setInterval = setInterval(function () { $scope.myTimer(); }, 1000);
$scope.myTimer = function () {
$scope.timer = $scope.timer.add('s', 1);
};

ngModel and resetting value

So have two directives that need to share data. Both are under the same controller, so set up the variable $scope.selection to store the selection, it gets a default value in the controller.
knowledge.controller('industryController', function($scope, mwFactory){
$scope.menudata={sections: [
{group: 'FMP', name: 'Finance'},
{group: 'FinTech', name: 'Financial Technology'},
]
}
if ($scope.selection) {
console.log("This is " + $scope.selection)
} else {
$scope.selection = 'Main_Page'
}
})
I then send that to a menu where you can make selection
<nav-circle group="section.group" ng-model="selection"></nav-circle>
I then set it as follows inside the directive
function nodeclick(d){
//console.log("Name is " + d.url);
console.log("Old model is " + ngModel.$modelValue)
ngModel.$modelValue = d.url;
ngModel.$viewValue = d.url;
console.log("New model is " + ngModel.$modelValue)
}
However, it does not seem like it is updating, or potentially even weirder, that something is resetting ngModel.
Got a call further up,
ngModel.$render = function () {
console.log("ngRender got called " + ngModel.$modelValue);
};
And this kicks off every minute or so, and always returns the value to the original value. What am I missing
OK, this may not be the best way, but it works, and sometimes that is enough:)
Instead of sending a variable I sent an object, and I think (someone who knows angular and javascript better may be able to explain/confirm) this means that the directive will be writing to a memory address rather than to a variable. Which also means that the ng-model will not change (the memory address is the same, the data stored at that memory address is changed).
Might be wrong, but the solution works as if that was the case.
So, define the scope variable:
$scope.selection = {};
$scope.selection.default = 'Main_Page'
$scope.selection.current = '';
Then send the following to the directives:
<nav-circle group="section.group" ng-model="selection.current"></nav-circle>
And to change the scope variable in the directive you just set viewValue
ngModel.$setViewValue(d.url);
As I mentioned, I am not certain if this is the right way, or if my understanding is correct, but it works:)

Sometime scope variable not getting set

This seems pretty strange to me but I hope there's someone that has come across this before and point me in the right direction.
I have a variable being set in scope within an $interval and the value is sometimes "sticking" and sometimes not.
someInterval = $interval(function() {
SomeFactory.getsomething($scope.highestnumber)
.then(function(response) {
if (response.number > $scope.highestnumber)
$scope.highestnumber = response.number;
});
}, 30000);
Most of the time this works - $scope.highestnumber is set with the updated value and 30 seconds later getSomething() is called passing the updated value.
However, every now and then (and I wish I could duplicate on demand), $scope.highestnumber is set with a new value but getSomething() is called with the value it had before the update executed. I have verified it by catching the value of $scope.highestnumber after it's been set to the new value, and then checking what's being passed into getSomething() on the next cycle.
So the sequence would be...
$scope.highestnumber = 10
getsomething(10) called
returns response.number = 11
$scope.highestnumber set to 11 (verified)
getSomething(10) called 30 seconds later

AngularJS e2e Testing: How To Get value of repeater().count()?

Problem
Calling repeater('#myTable tr','Rows').count(); returns a Future, not an integer. I need to get the integer value so I can confirm that an additional row was added to a table.
Code
it('should add a new user when save button is clicked',function()
{
showModal();
//here I'm trynig to store the row count of my table into a local variable.
//a future is returned who's 'value' field is undefined.
var memberCount = repeater('#memberTable tr','Member Rows').count();
//this outputs 'undefined'
console.log(memberCount.value);
input('editedMember.name').enter('John');
input('editedMember.grade').enter(5);
input('editedMember.ladderPosition').enter(3);
element('#saveMemberButton').click();
sleep(1);
expect(element(modalId).css('display')).toBe('none');
//here is where I want to do the comparison against the above stored memberCount
expect(repeater('#memberTable tr', 'Member Rows').count()).toBe(memberCount.value + 1);
});
Test Result
Chrome 25.0 e2e should add a new user when save button is clicked FAILED
expect repeater 'Member Rows ( #memberTable tr )' count toBe null
/Users/jgordon/learning/chessClub/web-app/test/e2e/scenarios.js:45:3: expected null but was 6
Chrome 25.0: Executed 2 of 2 (1 FAILED) (1 min 4.117 secs / 1 min 3.773 secs)
Drilling into the source code for Angularjs' e2e support reveals that you have to call execute() on the Future to have it populate its value. Also, when you call execute you have to provide a "done" function to the execute() otherwise Testacular will (oddly enough!) skip your test.
Code
var rowCountFuture = repeater('#memberTable tr','Member Rows').count();
rowCountFuture.execute(function(){
});
var memberCount = rowCountFuture.value;
While I'm jazzed to see this works, I'm concerned there may be some asynchronous bugs that could come out of this, also, I feel like this is a hack and not the right way to do it. Any ideas?
Based on the latest Protractor version:
it('should add a new user when save button is clicked', function() {
var memberCount;
element.all(by.repeater('#memberTable tr','Member Rows')).count().then(function(value) {
memberCount = value;
});
...
// then do all your entering user info, saving etc.
...
browser.refresh(); // or however you want to load new data
expect(element.all(by.repeater('#memberTable tr','Member Rows')).count()).toEqual(memberCount + 1);
});
I've run into the same issue, and have seen confusing results when testing value returned after calling execute(). I've found this method works more reliably:
var getCount = repeater('ul li').count();
getCount.execute(function(value) {
expect(value).toEqual(3);
});
You can do this most easily in the async promise returned by the locator
element.all(By.repeater 'thing in things').then(function(elements){
count = elements.length;
expect(count).toEqual(3);
});

Resources