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

Lookup as autocomplete #2

Closed
arjendeblok opened this issue Jul 31, 2020 · 21 comments
Closed

Lookup as autocomplete #2

arjendeblok opened this issue Jul 31, 2020 · 21 comments

Comments

@arjendeblok
Copy link
Contributor

I am trying your components as an alternative to mine.

What I made myself is an autocomplete. For example you want to select a contact.; you type in some letters; a request is going to the backend to search for a name starting with those letter; and a menu is shown where you can select the right contact.

I have tried to use the lookup for that. I have set the options field to a function that returns a list of contact depending on what you have typed in the input. I have a couple of problems with the current implementation.

  • Whenever you click on the input, the menu is shown, but nothing is there yet. My options function is not called either.
  • I would like to search only when the user has filled in more then 2 characters.

Are you planning this kind of functionality in the lookup or do you see this as a separate autocomplete control?
I could of course make it myself, but if you already planned this, I am not going to. I can help you of course if you like.

@MaximBalaganskiy
Copy link
Contributor

Could you please create a gist for this?
You can use this template https://gist.dumber.app/?gist=ca0cfc47e375e4b37363eeb407eb2859

@MaximBalaganskiy
Copy link
Contributor

options definition
options: ((filter: string, value: unknown) => Promise<unknown[]>) | unknown[] | undefined;
If it's a function it must return a Promise. There is also preload-options which forces the menu to be populated from the start

@arjendeblok
Copy link
Contributor Author

https://gist.dumber.app/?gist=01ac584061194a3093bb58cec8bbe8a6
I cannot get the SCSS for the menu and list to work.

@MaximBalaganskiy
Copy link
Contributor

dumber.app does not support @use in scss
try this

<template>
  <require from="@material/button/dist/mdc.button.css"></require>
  <require from="@material/list/dist/mdc.list.css"></require>
  <require from="@material/menu/dist/mdc.menu.css"></require>
  <require from="@material/menu-surface/dist/mdc.menu-surface.css"></require>
  <require from="@material/textfield/dist/mdc.textfield.css"></require>
  <require from="@material/typography/dist/mdc.typography.css"></require>
  <require from="./app.scss"></require>
  <!-- Try to create a css/scss/sass/less file then require it here -->
  <h1 mdc-headline3>${message}</h1>  
  <mdc-text-field label="Contact" ref="input"></mdc-text-field>
  <mdc-text-field-helper-line></mdc-text-field-helper-line>
  <mdc-lookup options.bind="search" preload-options
              value.bind="lookedUp & validateOnChange" input.bind="input">
    <template replace-part="option">
      ${option}
    </template>
  </mdc-lookup>

  <div>
  You selected "${lookedUp}"
  </div>
</template>

Also, your options function is incorrect - firstly, it does not filter and secondly, it ignores the second parameter which is a value.
Without filtering by value the logic will be broken.

@MaximBalaganskiy
Copy link
Contributor

You can have a look at the default options function provided by the component itself for the correct implementation

@arjendeblok
Copy link
Contributor Author

I updated the gist. I have now also included the second 'value' parameter in the function, but it is always undefined.

@MaximBalaganskiy
Copy link
Contributor

The value is not undefined when you pick an option, please observe the console carefully.
Here is the correct implementation

  async getOptionsDefault(filter: string, value: unknown): Promise<unknown[]> {
    const options = this.options as unknown[];
    if (value) {
      return Promise.resolve([options.find(x => this.getValue(x) === value)]);
    } else {
      return Promise.resolve(options.filter(x => this.getDisplay(x).toUpperCase().includes((filter || '').toUpperCase())));
    }
  }

@arjendeblok
Copy link
Contributor Author

Updated the gist again. I think it should be OK now. But I still cannot use it an an autocomplete. I set some remarks in the code why I cannot use it now for an autocomplete.

@MaximBalaganskiy
Copy link
Contributor

If you throw an error from the options function it will be displayed in a menu. The error is templateable as well.

@arjendeblok
Copy link
Contributor Author

Update gist again with a Promise reject. Looks OK, but I get an error that at initial load the reject is not catched.
After that it seems to work.

@MaximBalaganskiy
Copy link
Contributor

simple throw new Error() should work.
I actually don't see any uncaught reject errors in the console...

@MaximBalaganskiy
Copy link
Contributor

btw, if no element are found it's better to return an empty list. This handled differently and a templated "not found" item is shown

@MaximBalaganskiy
Copy link
Contributor

also, you need to either wrap text field and lookup with something with an mdc-menu-surface-anchor attribute or use hoist-to-body attribute on the lookup

@MaximBalaganskiy
Copy link
Contributor

@arjendeblok
Copy link
Contributor Author

I really wanted an autocomplete. So that only something happens if you type in something which is then autocompleted. So the 'Not Found' when just clicking the input is not what I want.
When the user just clicks the text field and gets an Not Found message he may not understand that he has to type something first.

@arjendeblok
Copy link
Contributor Author

arjendeblok commented Aug 3, 2020

I actually don't see any uncaught reject errors in the console...

If you change the reject when nothing is typed to a resolve with an empty list, then the reject error is not shown in the console.

@arjendeblok
Copy link
Contributor Author

I added the hoist-to-body

@arjendeblok
Copy link
Contributor Author

Please look at https://jqueryui.com/autocomplete/

@MaximBalaganskiy
Copy link
Contributor

I was looking at the app logs. There is indeed an error in the browser console which is fixable by a proper try/catch in the component.
As I mentioned, Not Found is templateable too. You could also return a special option with any text you wish.
As far as I can see, the only difference with the aforementioned autocomplete is that this lookup pops up immediately on mouse click.

@MaximBalaganskiy
Copy link
Contributor

MaximBalaganskiy commented Aug 4, 2020

Should be fixed via d4e8ebc
If for any reason a function returns undefined the menu will not open.
If you don't preload it will behave like jq plugin.

@arjendeblok
Copy link
Contributor Author

If the function returns a Promise returning undefined then it works really nice.
I can now use it as an autocomplete.

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