In angular dart is there a way to break early from a "foreach" loop - angular-dart

I saw that this is already answered for javascript but is there a way to break out of an forEach loop in angular dart.
bool hasValue() {
bool result = false;
periods.forEach((item) {
if (item.hasValue()) {
result = true;
//PENDING...Break out of loop early
}
});
return result;
}

As far as I know, you cannot break forEach loop.
You can try this code instead:
for(var item in items) {
final value = item['unit_value'];
if (value.isNotEmpty) {
break;
}
}

Related

Flutter: Concurrent modification during iteration

So I know that my mistake lies in trying to change my data when im iterating through it
this is the exact error
"Expected Non-error `Concurrent modification during iteration:
Instance of 'LinkedMap<dynamic, dynamic>'.
and this is my code:
_products.forEach((key, value) {
if (key.titel == product.titel) {
_products[key] += 1;
} else {
_products[product] = 1;
}
}
but I don't really get how I would be able to modify my data without iterating through it. Any suggestions?
----------------my Attempt -------------------
var _products = {}.obs;
var temp = {}.obs;
void addProduct(Product product) {
temp = _products;
if (_products.length > 0) {
_products.forEach((key, value) {
if (key.titel == product.titel) {
temp[key] += 1;
} else {
temp[product] = 1;
}
});
}
I get the same error; I think that is because in this line:
temp = _products;
I just get the reference on _products & I don't write _products in temp
So as mmcdon suggested you need make a copy of your existing thing that you want to iterate upon & iterate through that instead of your original piece
So in my case I need to do this:
var _products = {}.obs;
var temp = {}.obs;
void addProduct(Product product) {
temp = RxMap<dynamic, dynamic>.from(_products);
if (_products.length > 0) {
temp.forEach((key, value) {
if (key.titel == product.titel) {
_products[key] += 1;
} else {
_products[product] = 1;
}
});
}
So as you can see I iterate through temp, that basically is _products & Im writing the data that I need in _products

Dart non-async function return wait until for loop is complete

Here is my code
List<DocumentReference> getStacks(
List<DocumentReference> favoritePlayers,
List<DocumentReference> stacks,
) {
List<DocumentReference> newStacks = [];
for (var i = 0; i < stacks.length; i++) {
stacks[i].get().then((DocumentSnapshot stackSnapshot) {
if (stackSnapshot.exists) {
DocumentReference thisstack = stackSnapshot['player'];
for (var x = 0; x < favoritePlayers.length; x++) {
if (favoritePlayers[x] == thisstack) {
newStacks.add(stacks[i]);
}
}
}
});
if (stacks.length - 1 == i) {
return newStacks;
}
}
}
I do not have the option in the platform I am using to make the function async or Future, so I am trying to figure out a way to not return until both for loops are done. I have tried while loops and do while, but I guess I am missing something, this method is close, but it seems it still finishes before the inner loop does and wants to return nothing.
Any thoughts would be great.
In your code, the loop goes to the next operation without waiting for "stacks[i].get()" .
If the "stacks[i].get()" function is not a Future function, you can use it as follows.
List getStacks( List favoritePlayers, List stacks) {
List newStacks = [];
for (final stack in stacks) {
DocumentSnapshot stackSnapshot = stack.get();
//code
newStacks.add(stackSnapshot);
}
return newStacks;
}
If it is a future function, it should be like this;
Future<List> getStacks( List favoritePlayers, List stacks) async{
List newStacks = [];
for (final stack in stacks) {
DocumentSnapshot stackSnapshot = await stack.get();
//code
newStacks.add(stackSnapshot);
}
return newStacks;
}

block of coding running twice

So am having a scroll listener to get more data now the problem is that when the listener calls the function for more data then am having 4 if conditions but the function is running the if condition twice i don't understand the logic behind it.
MyCode:-
void _scrollListener()async{
if (!loading) {
if (scrollController.position.pixels == scrollController.position.maxScrollExtent) {
setState(() => load = true);
await clearEmptyDocs();
getMoreData();
}
}
}
getMoreData()async
{
var quicks;
var posts;
if(publicPostsDocuments.isNotEmpty)
{
print('1\n\n\n\n');
posts=await getPublicPosts();
}
if(publicQuicksDocuments.isNotEmpty)
{
print('2\n\n\n\n');
quicks=await getPublicQuicks();
}
if(publicPostsDocuments.isEmpty)
{
print('3\n\n\n\n');
posts=await getPublicDocuments();
}
if(publicQuicksDocuments.isEmpty)
{
print('4\n\n\n\n');
quicks=await getPublicDocumentsForQuicks();
}
setState(() {
load=false;
});
}
Here am having four lists and based on them am having if blocks so when lists are not empty then it should simply print 1 and 2 and then exit but it is printing 1,2,1,2 i.e. first 2 if blocks are running twice.

How to pass a test if expect fails

I have this code
it('This should pass anyway', function (done) {
testObj.testIt(regStr);
});
testObj
this.testIt = function (regStr) {
selector.count().then(function (orgCount) {
for (var curr = 0; curr < count; curr++) {
checkField(curr, regStr);
}
});
};
function checkField(curr, regStr) {
selector.get(curr).all(by.tagName('li')).get(0).getInnerHtml().then(function (text) {
expect(text).to.match(regStr, curr + '#ERR');
});
}
If one of these expects get a failure, test fails. How can i handle this? I mean - can i somehow count passed and failed expect()ations and return it? or, at least, dont let test break on first error.
I've tried try-catch, but nothing good happened.
it('This should pass anyway', function (done) {
try {
testObj.testIt(regStr);
} catch (e) {
console.log('#err' + e);
}
});
And then i wanted to use done(), but havent found any examples to do the similar. Can u please help me?
Sry for my english
UPD
You can return either null or a string from checkField(), join them up, and expect the array to be empty:
this.testIt = function (regStr) {
selector.count().then(function (orgCount) {
var errors = [];
for (var curr = 0; curr < orgCount; curr++) {
var e = checkField(curr, regStr);
if (e) { errors.push(e); }
}
assert.equal(0, errors.length, errors);
});
};
A cleaner approach would be to use map() to collect the data into an array:
var data = selector.map(function (elm) {
return elm.element(by.tagName('li')).getText();
});
expect(data).toEqual(["test1", "test2", "test3"]);

How to check if text is found in column in Protractor

I'm trying to assert that a name is displayed in a column of a table. I've written an inResults function that will iterate through a column's text to see if a name exists. Here's what I'm trying:
Page object:
this.names = element.all(by.repeater('row in rows').column('{{row}}'));
this.inResults = function(nameString) {
var foundit = '';
this.names.each(function(name) {
name.getText().then(function(it) {
console.log(it); // each name IS printed...
if(it == nameString) {
console.log('it\'s TRUE!!!!'); // this gets printed...
foundit = true;
}
});
});
return foundit; // returns '' but should be true?
};
Spec expect:
expect(friendPage.inResults('Jo')).toBeTruthy();
Both console statements print as expected... but my expect fails as foundit's value is still ''. I've tried this a number of ways and none are working. What am I missing?
I've devised what I think is a better/cleaner way to solve this. It's less complex and doesn't require locator/css code in the method.
friend.page.js
// locator
this.friendName = function(text) { return element.all(by.cssContainingText('td.ng-binding', text)) };
// method
this.inResults = function(name) {
return this.friendName(name).then(function(found) {
return found.length > 0;
});
};
friend.spec.js
expect(friendPage.inResults('Jo')).toBeTruthy();
I've added this to my protractor_example project on GitHub...
I would recommend you to use filter: http://angular.github.io/protractor/#/api?view=ElementArrayFinder.prototype.filter
this.inResults = function(nameString) {
return this.names.filter(function(name) {
return name.getText().then(function(text) {
return text === nameString;
});
}).then(function(filteredElements) {
// Only the elements that passed the filter will be here. This is an array.
return filteredElements.length > 0;
});
});
// This will be a promise that resolves to a boolean.
expect(friendPage.inResults('Jo')).toBe(true);
Use map to do this.This will return a deferred that will resolve with the values in an array, so if you have this:
this.mappedVals =element.all(by.repeater('row in rows').column('{{row}}')).map(function (elm) {
return elm.getText();
});
It will resolve like this:
this.inResults = function(nameString) {
var foundit = '';
mappedVals.then(function (textArr) {
// textArr will be an actual JS array of the text from each node in your repeater
for(var i=0; i<textArr.length; i++){
if(it == textArr[i]) {
console.log('it\'s TRUE!!!!'); // this gets printed...
foundit = true;
}
}
return foundit;
});
}
And Use that in Spec file like,
friendPage.inResults('Jo').then(function(findIt){
expect(findIt).toBeTruthy();
});