contact-picker
contact-picker copied to clipboard
Closer HTML alignment
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.
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?
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, 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?
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 => '[email protected]'
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.
Without going down a rathole (that I started, sorry! :)), I don't think you need the namespace:
- 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. - 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:
- 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). - 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.
- 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.
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.
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.
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 :)
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?
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.
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 https://github.com/WICG/contact-api/issues/12#issuecomment-480186692 I pointed to the vCard standard.
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.
It’s an agreed-on standard and parsing seems like a solved problem, but I see your point…
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.
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?