Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

this.myService is undefined when using Search Select dataSource #5

Closed
melroy89 opened this issue Apr 6, 2018 · 5 comments
Closed

Comments

@melroy89
Copy link
Contributor

melroy89 commented Apr 6, 2018

Hi,

I'm trying to use my own Angular service (like I already do for all my components) for my API call requests instead of directly calling HttpClient within the component.

Using a service is just a common practice, I don't know why this is not working. I'm getting: this.ledgerService is undefined.

  this.dataSource = {
      displayValue(value: any): Observable<OptionEntry | null> {
        ....
        return this.ledgerService.getOne(value) <!---------- Here is the problem somehow
        .pipe(
          map((ledger: Ledger) => ({
            value: ledger.ledger_id,
            display: `${ledger.ledger_number} - ${ledger.ledger_name}`,
            details: {}
          }))
       .....

Here you see my full code:
https://gitlab.melroy.org/snippets/13

Why is this not working but using HttpClient service is working in your example 🤕 ?

Kind regards,
Melroy van den Berg

@kylecordes
Copy link
Contributor

Hello, thanks for trying our library. I think the problem you're having is not specific to this library, but rather just an ordinary JavaScript this problem. Inside of your data source definition, this is referring to the data source, not to the outer component object. You can get the intended results by putting a line of code something like this right before the first line you quoted above:

const ledgerService = this.ledgerService;

Then inside the data source just refer to ledgerService rather than this.ledgerService.

There are also many other ways to structure the code to avoid this problem.

@melroy89
Copy link
Contributor Author

melroy89 commented Apr 6, 2018

OK interesting problem and 'work-around' in Javascript.

@melroy89
Copy link
Contributor Author

melroy89 commented Apr 6, 2018

You were right this is has again nothing to do with this library..

But I think the next issue (#6 ) will be, about embedding your search-select within a mat-form-fied block.

And the next next issue (#7 ), about the fact the drop-down (drop-up xD) list will be above the reachable browser screen. You 'solved' this by using some div occupying empty space below the select element.

This issue can now be closed. Thanks!

@melroy89
Copy link
Contributor Author

melroy89 commented Apr 7, 2018

You are right. There are other design solution to this problem. Like:

  constructor(
    ....
    public ledgerService: LedgerService,
  ) {
    this.dataSource = {
      displayValue(value: any): Observable<OptionEntry | null> {
        if (typeof value === 'string') {
          value = parseInt(value, 10);
        }
        if (typeof value !== 'number') {
          return of(null);
        }
        console.log("Get value of: " + value)
        return ledgerService.getOne(value)
        .pipe(
          map((ledger: Ledger) => ({
            value: ledger.ledger_id,
            display: `${ledger.ledger_number} - ${ledger.ledger_name}`,
            details: {}
          }))
        );
      },
      search(term: string): Observable<OptionEntry[]> {
        return ledgerService.getAll(undefined,
        { 'X-Pagination': 'false' },
        { 'rgs_ledger_reference_code[LIKE]': '%' + term + '%',
          'rgs_ledger_name[LIKE]': '%' + term + '%',
          'ledger_name[LIKE]': '%' + term + '%',
          // Add 'OR' between every LIKE operator (instead of AND)
          '_dir_where': 'OR'
        })
        .pipe(
          map(resp => resp.body),
          map((list: Ledger[]) =>
            list.map(ledger => (
            {
              value: ledger.ledger_id,
              display: `${ledger.ledger_number} - ${ledger.ledger_name}`,
              details: {}
            }))
          )
        );
      }
    };
  }

@kylecordes
Copy link
Contributor

Here is a tip for anyone who stumbled across this later. Whether you are implementing a DataSource for this search select widget, or a DataSource for one of the built-in Angular Material widgets (I borrowed the DataSource notion from their), it makes sense for simple data sources to be implemented as literal objects like the code snippets above. But if you have a more complex data source for one more likely to be reused, consider implementing it as a normal class (with the class keyword).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants