1

Need to find the count of the element from arryelement and if the count>1 then need to click

/*search name is clinic name
clinicsearch is the arrayelement which has the list of clinic name list from the table*/
public SearchAndSelectClinicA(SearchName:string){
  this.ClinicSearch.sendKeys(SearchName);
  this.SearchIcon.click(); //click on the icon to get the clinic names
  this.SearchedClinic.count().then(function(count){
    //get the count of elements which are there in the Searchedclinic element array
    if(count>1){
      this.SearchedClinic.each(function(rows){ 
        /*Failed: Cannot read property 'SearchedClinic' of undefined 
          (Error gets displayed when it comes to above line.*/
        rows.getText().then(function(value){
          if(value.indexOf(SearchName)){
            //Click the element if the statement is satisfied
            rows.click();
          }
        });
      });
    }
  });
}

Please help me in solving this

Failed: Cannot read property 'SearchedClinic' of undefined.

Is getting displayed.

It is able to execute till the if statement. Later it throws error as specifief above and the exection stops immediately

DtestA
  • 55
  • 9
  • can you edit your post i think you mismatch to insert code sample, it is difficult to read – Benjamin Caure May 31 '18 at 15:16
  • Show the error message you get. What has your debugging shown you? What research have you done? These details should be in the question as an [edit] –  May 31 '18 at 15:31
  • Possible duplicate of [How does the "this" keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – georgeawg Aug 19 '18 at 15:43

3 Answers3

3

In JavaScript each function has an implicit this. You need be careful when use this in nested function situation.

Following picture illustrate those this come from which function.

enter image description here

The second this.SearchedClinic will try to access this belongs to the nested function: function(count){}, which has no a property called SearchedClinic.

You expect that this point to the upper one. So you need to assign the top this to another variable as below:

enter image description here

Now me is point to the top this, you can use it in any nested function as you want.

yong
  • 11,757
  • 1
  • 10
  • 23
1

Your function(rows) creates a new closure. That means that this within that scope is not necessarily the same as the this outside.

A couple solutions are to

  1. Define a different variable above such as var self = this; the inside the function use

    self.SearchedClinic`
    
  2. Use a ES6 function definition that uses the same scope.

    this.SearchedClinic.count().then((count) => { 
    });
    
  3. Use .bind(this)

    this.SearchedClinic.count().then((function (count) => { 
    }).bind(this));
    
georgeawg
  • 46,994
  • 13
  • 63
  • 85
hassassin
  • 4,844
  • 1
  • 25
  • 37
0

suppose the following code:

const result = obj1.printName.call(obj2);

using this under the function call will reference to obj2 since the first parameter of call() is to explicitly set what this refers to.

This is exaclty the problem you're encountering with.

this.SearchedClinic.count().then(function(count){ 
    //calling this will reference the parameter count 
}

any this in between accolades will reference the first parameter of the function. What you would do, is to declare a global variable: var searchedClinic = this.SearchedClinic. Here is your code updated:

public SearchAndSelectClinicA(SearchName:string){
  var searchedClinic = this.SearchedClinic;
  this.ClinicSearch.sendKeys(SearchName);
  this.SearchIcon.click(); //click on the icon to get the clinic names
  this.SearchedClinic.count().then(function(count){
    //get the count of elements which are there in the Searchedclinic element array
    if(count>1){
      searchedClinic.each(function(rows){ 
        rows.getText().then(function(value){
          if(value.indexOf(SearchName)){
            //Click the element if the statement is satisfied
            rows.click();
          }
        });
      });
    }
  });
}