-
-
Notifications
You must be signed in to change notification settings - Fork 26
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
Design #2
Comments
The distal explanation is that Mutations are a special case because of things like the However, in our library, we're not providing web-components per se, instead we're making base classes which authors are meant to extend, so whereas a polymer implementation of apollo would look like: <apollo-query query="[[query]]" data="{{data}}"></apollo-query>
<my-view data="[[data]]"></my-view> Our library extends LitElement to make it easier to integrate your apollo-client into your elements: <script type="module">
import gql from 'graphql-tag'
import { ApolloQuery, ApolloMutation, html } from 'lit-apollo';
customElements.define('view-element', class ViewElement extends ApolloQuery {
_render({data}) {
return html`
<h1>value is ${data.value}</h1>
<mutate-input></mutate-input>
`;
}
});
customElements.define('mutate-input', class MutateInput extends ApolloMutation {
_render({ value }) {
return html`
<input
value="${value}"
on-input="${e => this.mutate({ variables: { value: e.target.value } })}">`;
}
constructor() {
super();
this.mutation = gql`mutation($input: String) { updateInput(input: $input) { value }`;
}
});
</script>
<view-element>
<!-- this sets the `query` property on view-element -->
<script type="application/graphql">query { input { value } }</script>
</view-element> |
@bennypowers Are there any plans to implement web component(s) (on top of your base classes)? Using lit-element doesn't mean you can't create web components like using Polymer. You can just use LitElement instead of PolymerElement as base class. Material Web Components are good example of set of web components built on top of LitElement. Your current implementation looks very much like https://github.com/aruntk/polymer-apollo. But I like more https://webcomponents.org/element/reach-digital/polymer-apollo-client. The only downside is that it doesn't support GraphQL real-time subscriptions (updates). Please look at aruntk/polymer-apollo#21 and my big comments FirebaseExtended/polymerfire#274 (comment) and FirebaseExtended/polymerfire#274 (comment) to see why declarative web components better than mixins / base classes. What do you think about this? |
Can you show me an example of a document you'd like to build with these elements? How would It look, what would the APIs be like? I want to get a better idea of your use case. |
Since web components are interoperable, they can be used in a Polymer project, despite the fact that they themselves are written using lit-element. Something like: If I use apollo web components in import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-input/paper-input.js';
// import apollo web components
class MyView extends PolymerElement {
static get properties() {
return {
searchId: {
type: String
},
data: {
type: Object
}
}
}
static get template() {
return html`
<paper-input value="{{searchId}}"></paper-input>
<apollo-config uri="https://graphql.endpoint/graphql"></apollo-config>
<apollo-client
query='{
post(id: "[[searchId]]") {
id
title
content
published
}
}'
data="{{data}}">
</apollo-client>
Post title: [[data.post.title]]
Post content: [[data.post.content]]
`;
}
}
customElements.define('my-view', MyView); If I use apollo web components in import {LitElement, html} from '@polymer/lit-element/lit-element.js';
import '@polymer/paper-input/paper-input.js';
// import apollo web components
export class MyView extends LitElement {
static get properties() {
return {
searchId: String,
data: Object
}
}
onValueChanged(e) {
this.searchId = e.detail.value;
}
onDataChanged(e) {
this.data = e.detail.value;
}
_render({searchId, data}) {
return html`
<paper-input on-value-changed="${this.onValueChanged.bind(this)}"></paper-input>
<apollo-config uri="https://graphql.endpoint/graphql"></apollo-config>
<apollo-client
query='{
post(id: "${searchId}") {
id
title
content
published
}
}'
on-data-changed="${this.onDataChanged.bind(this)}">
</apollo-client>
Post title: ${data.post.title}
Post content: ${data.post.content}
`;
}
}
customElements.define('my-view', MyView); GraphQL varibles When the GraphQL real-time subscriptions (updates) <apollo-client
subscription='{
post(published: true) {
id
title
content
published
}
}'
data="{{data}}">
</apollo-client> When published posts (posts with Desing questions First variant — one single universal <apollo-client
query=""
data="">
</apollo-client>
<apollo-client
mutation=""
data="">
</apollo-client>
<apollo-client
subscription=""
data="">
</apollo-client> Second variant — one single universal <apollo-client
query='
query {
users {
id
name
email
isAdmin
}
}'
data="">
</apollo-client>
<apollo-client
query='
mutation {
createUser(data: {
name: "Alice"
email: "[email protected]"
}) {
id
}
}'
data="">
</apollo-client>
<apollo-client
query='
subscription {
post(published: true) {
id
title
content
published
}
}'
data="">
</apollo-client> |
Variables in GraphQL uses Is it possible to use (Polymer) data binding and GraphQL |
Looks like it is possible to write queries in the body of web component, not in <apollo-client result="{{data}}">
query Pagination($skip: Int!) {
allStarships(first: 5, skip: $skip) {
name
class
}
}
</apollo-client> or <apollo-client result="{{data}}">
<script type="application/graphql">
query {
allStarships(first: 5, filter: {pilots_some: {name_not: ""}}) {
name
class
pilots {
name
homeworld {
name
}
}
}
}
</script>
</apollo-client> What is better? Is it possible to use varibles if the query placed in the body of web component (not in static get template() {
return html`
<apollo-client data="{{data}}">
query {
post(id: [[searchId]]) {
id
title
content
published
}
}
</apollo-client>
`;
} or _render({searchId}) {
return html`
<apollo-client on-data-changed="${this.onDataChanged.bind(this)}">
query {
post(id: ${searchId}) {
id
title
content
published
}
}
</apollo-client>
`;
} Will it work inside static get template() {
return html`
<apollo-client data="{{data}}">
<script type="application/graphql">
query {
post(id: [[searchId]]) {
id
title
content
published
}
}
</script>
</apollo-client>
`;
} or _render({searchId}) {
return html`
<apollo-client on-data-changed="${this.onDataChanged.bind(this)}">
<script type="application/graphql">
query {
post(id: ${searchId}) {
id
title
content
published
}
}
</script>
</apollo-client>
`;
} |
Should I escape <apollo-client
query="{ repository(owner: \"bennypowers\", name:\"lit-apollo\") { url } }"
last-response="{{response}}">
</apollo-client> Seems if I use <apollo-client
query='{ repository(owner: "bennypowers", name: "lit-apollo") { url } }'
last-response="{{response}}">
</apollo-client> |
Should I wrap string variables in double quotes? I.e. <apollo-client
query='{
post(id: "[[searchId]]") {
id
title
}
}'
data="{{data}}">
</apollo-client> insted of <apollo-client
query='{
post(id: [[searchId]]) {
id
title
}
}'
data="{{data}}">
</apollo-client> or <apollo-client
query='{
post(id: "${searchId}") {
id
title
}
}'
on-data-changed="${this.onDataChanged.bind(this)}">
</apollo-client> instead of <apollo-client
query='{
post(id: ${searchId}) {
id
title
}
}'
on-data-changed="${this.onDataChanged.bind(this)}">
</apollo-client> |
First of all thank you for the detailed descriptions. There are a few things I think we need to consider here:
customElements.define("apollo-query", class ApolloQueryElement extends ApolloQuery {
fire(type, detail) {
this.dispatchEvent(new CustomEvent(type, {
bubbles: true,
composed: true,
detail,
}
}
_propertiesChanged(props, changedProps, oldProps) {
super._propertiesChanged(props, changedProps, oldProps);
const {data, error, loading, networkStatus} = changedProps;
(data) && this.fire("data-changed", { value: data });
(error) && this.fire("error-changed", { value: error });
(loading) && this.fire("loading-changed", { value: loading });
(networkStatus) && this.fire("network-status-changed", { value: networkStatus });
}
}) That would provide a similar API to the currently available polymer2 Apollo components. I'd be happy to provide such a component under Would that, and perhaps some guidance around bundling in the README, be enough to cover your case? |
It would be very great.
Look like it's possible to bundle only apollo-client (not the whole app). See e.g.: https://github.com/reach-digital/polymer-apollo-client/blob/master/build/apollo-client.js |
It's not that simple if you want to use custom authentication, subscription transport, etc. I think the apollo developers are set in their ways about requiring (and encouraging) a build step, and until that changes, I'd rather not let on that it's easy to just plug in some pre-made components and get a fully-functional apollo client |
@unicodeveloper PTAL, need your help. |
It seems that |
typo :) Slightly more legit answer: The design for ApolloMutation is still a WIP. I'm not amazingly happy with the way it is now - you may have to define a new component for each type of mutation. So if your app has 20 kinds of text property mutations, that could potentially be 20 different mutations. |
Version 0.1.0 updates the readme to include the example p3-compatible component. Is that enough to close this issue? |
I’ve been considering making <apollo-mutation mutation="${mutation}" mutate-on="input">
<input slot="mutator"/>
</apollo-mutation> where mutate-on accepts an event name, which it would listen for on the element in the I think the pros to this approach would be DX - not having to create a new one-off class with its own What would be the implications for styling/dom? |
Closing in favour of #11 |
If I understand correctly, mutations and subscriptions in GraphQL are also queries (special queries).
So what about the only single one universal web component instead of 3 (
<apollo-query>
,<apollo-mutation>
,<apollo-subscription>
)?The text was updated successfully, but these errors were encountered: