A quick note on sendKeys and e1
A quick note that sendKeys does not return a WebElement or ElementFinder. This means that e1 in the example above is probably undefined.
Stale elements and the DOM changing
Quick note on assumptions: The answer has an assumption that sending text to a filter would change the row count or number of elements on the screen. If there are the same number of elements on the screen after you send in the text, then this would not work. I would look at Florent's comment below on the stale reference error.
Stale elements usually happen when the DOM has changed. If you are using some structural directive in Angular, the DOM will change if you are using *ngFor or *ngIf. My guess is that after you filter the the element, you are getting the elements in the DOM during or before the DOM actually changes based on your filter. This would result in a stale referenced web element. In my examplex below, I am using async / await with the control flow off.
Explicit wait during the filter
You could explicitly set a sleep so the DOM will update before you make a call to click the first element. This could lead to potentially flaky tests because the timeout is unknown based on the environment you will run in.
it('should do something', async () => {
const filterItem = element(by.id('FiltItemTransDocNo'));
await filterItem.sendKeys(grno);
await browser.sleep(1000); // or some other waits
await element.all(by.name('chkGrd')).first().click();
});
Compare rows for element.all
Alternatively you could do a comparison check for the amount of element.all items you have before and after the click and only move on when things are updated.
it('should do something', async () => {
const filterItem = element(by.id('FiltItemTransDocNo'));
const table = element.all(by.name('chkGrd'));
const length = await table.count();
await filterItem.sendKeys(grno);
// After the filter keys are sent, check to see if the current table
// count is not equal to the `table.count()`.
let updated = false;
await browser.wait(async () => {
updated = length !== await table.count();
return updated;
}, 5000);
// So if we use the entire 5 seconds and the count has not changed,
// we should probably fail before clicking on stuff.
expect(updated).toBeTruthy();
// now we can click on the next element.
await element.all(by.name('chkGrd')).first().click();
});
Why does calling length !== await table.count() work? This is because the table represents a promise to get the web element. When you call the count method, it executes the action by first resolving the web element. This could potentially be different depending if the DOM changes. We then compare the current count to the previous one.
Making sure you are using async / await
In your configuration file, you will need to specify that you are off the control flow:
exports.config = {
// In this case, I plan to use a selenium standalone server
// at http://127.0.0.1:4444/wd/hub. You could also use other
// methods like direct connect or starting it up with 'local'.
seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
// Required flag to tell Protractor you do not want to use the
// control flow. This means that you will have to either chain
// your promises or async / await your actions. Historically
// jasminewd node module would resolve promises for you. This
// package will no longer be used in future releases since the
// control flow is deprecated.
SELENIUM_PROMISE_MANAGER: false,
// The rest of your config...
}
Hope that helps.