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

Closer HTML alignment #21

Open
marcoscaceres opened this issue Aug 5, 2019 · 16 comments
Open

Closer HTML alignment #21

marcoscaceres opened this issue Aug 5, 2019 · 16 comments

Comments

@marcoscaceres
Copy link
Member

Random thought... I wonder if ContactProperty should actually reflect the list of HTML autocomplete names... and, instead of returning a ContactInfo dictionary, the API just returned FormData?

That might be nice, because then you can just POST contacts directly (or use the FormData API to query what you got back). That also works nicely if the API is not available, because then the developer would just fall back to a HTML form.

@aarongustafson
Copy link

I like this idea. How would you see it working with selecting multiple contacts, for instance? Would you see it being a repeated fieldset (containing those autocomplete fields) that would be supplanted by this API, if available?

@rayankans
Copy link
Collaborator

I like the idea of re-using autocomplete names, we might have to do something about icons though.

@marcoscaceres, I'm assuming you mean returning a list of FormData (one per contact), instead of a list of ContactInfo. I think that's a bit awkward with multiple contacts, since you'd have to combine them to create a ContactInfo-like object to serialize them if your goal is just uploading/storing the contacts.

On the other hand, if you goal is to display them in a form before uploading it would be pretty easy to create a form with repeated fieldsets from the ContactInfos (like @aarongustafson suggested).

@marcoscaceres
Copy link
Member Author

@marcoscaceres, I'm assuming you mean returning a list of FormData (one per contact), instead of a list of ContactInfo.

No, was thinking just one FormData object... but...

I think that's a bit awkward with multiple contacts, since you'd have to combine them to create a ContactInfo-like object to serialize them if your goal is just uploading/storing the contacts.

Perhaps. I wonder how clunky would it be to use a single FormData object, given that it supports multiple keys?

@rayankans
Copy link
Collaborator

Perhaps. I wonder how clunky would it be to use a single FormData object, given that it supports multiple keys?

I'd imagine the FormData would look something like this, since we'd have to namespace which contact that field belongs to, and the value has to be a string or a blob:

const formData = await navigator.contacts.select(['name', 'email'], {multiple: true});
print(formData);
// c1.name => 'Rayan'
// c1.name => 'rayankans'
// c2.name => 'marcoscaceres'
// c2.email => 'marcos@marcosc.com'

Getting field values would work nicely, even for missing / unshared fields:

formData.getAll('c1.name');  // ['Rayan', 'rayankans']
formData.getAll('c1.email');  // []

But getting the number of contacts is a bit awkward (unless explicitly passed over as well).

new Set([...formData.keys()].map(k => k.split('.')[0])).size;  // 2

I personally find the data in this format hard to interact with, specifically the contact namespacing. One entry per contact in a list is easier to reason about, and easier to transform into any other format.

@marcoscaceres
Copy link
Member Author

Without going down a rathole (that I started, sorry! :)), I don't think you need the namespace:

  1. the caller is the one that requested the contact fields (["name", "email"]), so the API always gives you back the fields, even if they contain no data.
  2. the number of returned contacts is always keys' length/2 (with empties being the empty string).

I guess ultimately what I'm trying to get to with the FormData and HTML autocomplete names is that this information is closely related to HTML Forms... the Credential Management API is another spec that used HTML autocomplete names in a really nice way to create its own objects.

I know I'm telling you things you all already know, but the primary use cases would appear to be:

  1. sending the contacts to a server: the dictionary is simple nice enough that it can just be stringified into JSON. However, for legacy sites that are posting, it means mapping the structure into form fields, and then likely POSTing those (so we are back at FormData).
  2. display - for which either FormData or a dictionary may be suitable.

I think I saw you opted to use a dictionary instead of an interface, but I'm imagining something cute like:

interface ContactInfo extends FormData {
};

Or:

interface ContactInfo {
   ... stuff... 
  FormData toFormData();
  [default] object toJSON();  
}

anyway, these are all half-baked ideas... but wanted to plant a few seeds.

@rayankans
Copy link
Collaborator

  1. the number of returned contacts is always keys' length/2 (with empties being the empty string)

I don't think that's true, in the example I constructed c1 has multiple names. Since the FormData entry value has to be a string (or blob, but not applicable in this case), we would need one entry per a contact's property.

I really like switching the ContactInfo to an interface though. It would also solve the feature detection issue #19 I've been considering (thanks for the seed :) ). It's not clear to me though if in your proposed example ContactInfo is per contact, or for all contacts. If it's for all contacts it has the same pitfalls previously discussed. If it's one per contact toFormData wouldn't add much value.

@marcoscaceres
Copy link
Member Author

I was thinking one ContactInfo per contact too, and then we could maybe have a static method:

ContactInfo.toFormData(...contacts);

Which merges them into a single FormData that one could later POST.

@rayankans
Copy link
Collaborator

Alright, so putting everything together, this is the new proposed structure:

interface ContactInfo {
    sequence<DOMString> name;
    sequence<DOMString> email;
    sequence<DOMString> tel;
    [default] object toJSON();
    static FormData toFormData(sequence<ContactInfo> contacts);
};

The chosen field names happen to already match the autocomplete names.

I still have a few concerns regarding toFormData, mainly being that we would still need to apply some form of per-contact namespacing, which will be inflexible. @marcoscaceres, how would you feel about letting legacy sites that need to post through a form create their own FormData object? It's simple enough that it's a few lines of code and they will probably prefer matching their server-side implementation from the client rather than changing their server-side implementation to match the weird FormData structure we will need to come up with.

@marcoscaceres
Copy link
Member Author

It's simple enough that it's a few lines of code and they will probably prefer matching their server-side implementation from the client rather than changing their server-side implementation to match the weird FormData structure we will need to come up with.

Re: FormData, I'm ok with the above.

I'm not sure about the sequences:

sequence<DOMString> name;
sequence<DOMString> email;
sequence<DOMString> tel;

I'd suggest just a single value for each. Otherwise it can get a bit crazy because it will inconsistent across UAs what returned order means.... also, from our experience with Payment Request, mapping to NSPersonComponent is hard. If we want alternative names or whatever, then we should add fields for that (again matching what autocomplete in HTML does).

And geessss... I eventually want:

[Constructor(ContactInfo)]
interface ContactInfo extends PaymentAddress {};

But getting ahead of myself :)

@beverloo
Copy link
Member

beverloo commented Aug 8, 2019

From the peanut gallery: most address books support multiple values for most fields, and looking at my own contact list this applies to many individuals. How would we represent that data w/o sequences?

@marcoscaceres
Copy link
Member Author

I was thinking about the same thing today while looking at both Contacts.app and the HTML spec. Let’s take phone number as a case: in iOS’s contacts, you can have home, work, mobile, main, iPhone, and so on. The current tel sequence obviously can’t distinguish between them.

I think this why we need something MapLike that works similarly to HTML autocomplete.... and why I instinctively reached for FormData (even though it was admittedly the wrong choice!).... but I still think we need something that can capture and distinguish between “home tel” and “work tel”.

Again, take a look at how elegantly HTML autocomplete is able to declaratively extract the right information. We need something similar, and as fine grained.

@tomayac
Copy link

tomayac commented Aug 8, 2019

Again, take a look at how elegantly HTML autocomplete is able to declaratively extract the right information. We need something similar, and as fine grained.

In #12 (comment) I pointed to the vCard standard.

@marcoscaceres
Copy link
Member Author

Just noting the case in #12 is covered by payment request api (heh, I’m totally not biased! 😂)... but Tom’s right about the scope of the problem - and I imagine none of us want to parse vCard or give developers back vCard data 🤢.

I feel like the right solution is within our grasp tho.

@tomayac
Copy link

tomayac commented Aug 8, 2019

It’s an agreed-on standard and parsing seems like a solved problem, but I see your point…

@markcellus
Copy link

I can see why the API should be closely aligned to the HTML standard but not sure if FormData is the right API for this to follow. Is there any reason why the assumption is for these contacts to be only interoperable with HTML forms? I would imagine implementors may want to do something with the data other than submit it through a form.

@marcoscaceres
Copy link
Member Author

I would imagine implementors may want to do something with the data other than submit it through a form.

Apart from displaying it and POSTing it, what else are you envisioning?

I guess “sharing” using web share would be pretty useful. Anything else?

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

6 participants