✨PWA: Expose amp-bind getState and setState#25011
✨PWA: Expose amp-bind getState and setState#25011dreamofabear merged 15 commits intoampproject:masterfrom mattwomple:patch-3
Conversation
Expose shadowDoc.getState and shadowDoc.setState methods for PWAs.
|
@choumx Initial thoughts welcome. I'm actually blocked on testing .setState because this promise seems to hang (at least in localhost testing): amphtml/extensions/amp-bind/0.1/bind-impl.js Line 1024 in bcdd618 Oh, I see, ww.js isn't lazy building: |
src/runtime.js
Outdated
| * a copy of the value of a state | ||
| */ | ||
| getState: name => { | ||
| return Services.bindForDocOrNull(shadowRoot).then(bind => { |
There was a problem hiding this comment.
For pages that do not use amp-bind, this promise never resolves. I don't think it's a problem, but wanted to make sure this received consideration.
There was a problem hiding this comment.
Hm, it should resolve with null on pages that are missing the extension script in the doc head.
src/runtime.js
Outdated
| * @return {Promise} - Resolves after state and history have been updated | ||
| */ | ||
| setState: state => { | ||
| return Services.bindForDocOrNull(shadowRoot).then(bind => { |
src/runtime.js
Outdated
| */ | ||
| getState: name => { | ||
| return Services.bindForDocOrNull(shadowRoot).then(bind => { | ||
| return bind && bind.getStateCopy(name); |
There was a problem hiding this comment.
This should probably be changed to:
return bind ? bind.getStateCopy(name) : Promise.resolve();
| return Services.bindForDocOrNull(shadowRoot).then(bind => { | ||
| return ( | ||
| (bind && bind.setStateAndUpdateHistory(state)) || Promise.resolve() | ||
| ); |
There was a problem hiding this comment.
This would be more readable as:
return bind ? bind.setStateAndUpdateHistory(state) : Promise.resolve();
spec/amp-shadow-doc.md
Outdated
| - `shadowDoc.postMessage()` and `shadowDoc.onMessage()` - can be used to message with the AMP document. | ||
| - `shadowDoc.close()` - closes the AMP document and frees the resources. | ||
| - `shadowDoc.bind.getState(expr)` - Get an `amp-bind` state from the AMP document using expression syntax | ||
| - `shadowDoc.bind.setState(obj)` - Deep merge an object into the AMP document's global `amp-bind` state |
There was a problem hiding this comment.
IMO it's fine to not namespace this under .bind since we don't namespace the on="tap:AMP.setState(...)" action either.
spec/amp-shadow-doc.md
Outdated
| - `shadowDoc.setVisibilityState()` - changes the visibility state of the AMP document. | ||
| - `shadowDoc.postMessage()` and `shadowDoc.onMessage()` - can be used to message with the AMP document. | ||
| - `shadowDoc.close()` - closes the AMP document and frees the resources. | ||
| - `shadowDoc.bind.getState(expr)` - Get an `amp-bind` state from the AMP document using expression syntax |
There was a problem hiding this comment.
Let's mention that expr is a JSON expression string e.g. "foo.bar".
extensions/amp-bind/0.1/bind-impl.js
Outdated
| * @param {string} expr | ||
| * @return {(?JsonObject|string|undefined)} | ||
| */ | ||
| getStateCopy(expr) { |
There was a problem hiding this comment.
Nit: Let's just call this getState(). There shouldn't be a use case for returning a non-copy.
extensions/amp-bind/0.1/bind-impl.js
Outdated
| // Support expressions | ||
| if (typeof state === 'string') { | ||
| // Emulate UIEvent 'click' | ||
| return this.pushStateWithExpression( |
There was a problem hiding this comment.
A bit confusing if this API can both "set" and "push" state. I think it's worth separating into two APIs.
Though for the sake of keeping this PR small, can we remove this case?
There was a problem hiding this comment.
To make sure I understand, are you suggesting that we do not update history with the shadowDoc.setState() method?
There was a problem hiding this comment.
I mean removing this case where passing a string calls "push" instead of "set". The former appends a new entry onto the history stack.
There was a problem hiding this comment.
Or maybe you just meant to call setStateWithExpression here?
| this.history_.replace(data); | ||
| } | ||
| }); | ||
| return this.setStatePromise_; |
There was a problem hiding this comment.
Would be nice to de-dupe this code snippet with setStateWithExpression. Feel free to create a new private helper method or just drop a TODO(choumx) here for me.
|
Thank you for the review! I believe all review comments are resolved in 1a1582e. |
dreamofabear
left a comment
There was a problem hiding this comment.
Looks good overall.
/cc @dvoytenko FYI a new shadow API for amp-bind.
src/runtime.js
Outdated
| // Emulate UIEvent 'click' | ||
| return bind.setStateWithExpression( | ||
| /** @type {string} */ (state), | ||
| /** @type {!JsonObject} */ ({event: 1}) |
There was a problem hiding this comment.
I haven't dug too deep into how the scope parameter is used, but at least an empty object needs to be passed. I opted to mimic the object that is passed by a single click event here.
There was a problem hiding this comment.
Empty object will suffice then. :)
It's used for things like on="submit-success: AMP.setState({foo: event.response})", but there's no real "event context" in this case.
|
Great contribution! |
* PWA: Expose getState and setState Expose shadowDoc.getState and shadowDoc.setState methods for PWAs. * PWA: Remove inconsistent return value for setState * Minor cleanup * Fix check-types * Add micro documentation for PWA (get/set)State * Support PWA setState with expression syntax * Fixup types * Review updates and add tests * Fix check-types * Fix empty string return value from getState * Don't limit return type of getState * Fix unit test * Do not emulate event in setState * Really fix unit test
* PWA: Expose getState and setState Expose shadowDoc.getState and shadowDoc.setState methods for PWAs. * PWA: Remove inconsistent return value for setState * Minor cleanup * Fix check-types * Add micro documentation for PWA (get/set)State * Support PWA setState with expression syntax * Fixup types * Review updates and add tests * Fix check-types * Fix empty string return value from getState * Don't limit return type of getState * Fix unit test * Do not emulate event in setState * Really fix unit test
Allow PWAs to access
amp-bindmethods through theshadowDocinstance created byAMP.attachShadowDoc():shadowDoc.getState(expr)- Get anamp-bindstate from the AMP document using a JSON expression stringshadowDoc.setState(state)- Deep merge an object or expression into the AMP document's globalamp-bindstateFixes #24982