aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.44k stars 2.13k forks source link

hideSignUp doesn't work with amplify-authenticator - Vue 3.x #6998

Closed csbszb closed 4 years ago

csbszb commented 4 years ago

Describe the bug When I use the amplify-authenticator component in a new project and try to hide the sign up link the hide-sign-up attribute doesn't work properly

To Reproduce Steps to reproduce the behavior:

  1. Create new Vue 3.x app with vue create myamplifyproject (choose default values)
  2. Add Amplify packages npm install aws-amplify @aws-amplify/ui-components
  3. Import components in src/main.js
    
    import { createApp } from 'vue'
    import App from './App.vue'

import { applyPolyfills, defineCustomElements } from '@aws-amplify/ui-components/loader';

applyPolyfills().then(() => { defineCustomElements(window); });

const app = createApp(App);

app.config.isCustomElement = (tag) => tag.startsWith('amplify-'); app.mount('#app');


4. Add template to `App.vue`
``` javascript
<template>
  <amplify-authenticator username-alias="email">
    <amplify-sign-in hide-sign-up="true" />
  </amplify-authenticator>
</template>
  1. Start app with npm run serve

Expected behavior The sign up block is hidden and can't see the "No account? Create account" option

Additional context I started a debugger and saw that the <amplify-sign-in> component's render method is called twice. The first time the hideSignUp attribute is correctly set to true, however when it's called the second time this value is overwritten with false

amhinson commented 4 years ago

@csbszb Could you provide your package.json, or specifically the versions of the Amplify packages you are using?

csbszb commented 4 years ago

hey @amhinson, this is the package.json

{
  "name": "myamplifyproject",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@aws-amplify/ui-components": "^0.8.7",
    "aws-amplify": "^3.3.4",
    "core-js": "^3.6.5",
    "vue": "^3.0.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0-0"
  }
}
amhinson commented 4 years ago

It looks like you also need to add slot="sign-in" to the amplify-sign-in component. Since you aren't putting it in the slot, I think that explains the behavior of 2 versions showing because amplify-authenticator will render the sign in component as well.

Could you try using @aws-amplify/ui-vue instead of @aws-amplify/ui-components? https://docs.amplify.aws/ui/q/framework/vue

csbszb commented 4 years ago

Unfortunately it won't work because: 1) In Vue 3 'slot' attributes are deprecated and are replaced with v-slot:slotname but named slots can be only used with a <template> element 3) @aws-amplify/ui-vue also doesn't work with Vue 3, see here: #6756

amhinson commented 4 years ago

Ah thanks for the info @csbszb. It looks like StencilJS, which we use for our UI components, is still working on Vue 3 support.

https://github.com/ionic-team/stencil-ds-output-targets/pull/94

We will track this and update our library once the Stencil PR is released.

amhinson commented 4 years ago

II'm also going to close this particularly issue so we can track it in the other feature request issue you linked to.

brnovk commented 3 years ago

It looks like the problem is still reproduced. As hot-fix, i will publish a temporary solution - deleting a button with JavaScript (attention - this is a dirty code):

src/App.vue

<template>
    <div id="root">
        <div v-if="authState !== 'signedin'">
            <div>You are signed out.</div>
        </div>
        <amplify-authenticator>
            <div v-if="authState === 'signedin' && user">
                <amplify-sign-out></amplify-sign-out>
            </div>
        </amplify-authenticator>
    </div>
</template>
<script>
    import { onAuthUIStateChange } from '@aws-amplify/ui-components'
    export default {
        name: 'App',
        components: {
        },
        created() {
            this.unsubscribeAuth = onAuthUIStateChange((authState, authData) => {
                this.authState = authState;
                this.user = authData;
            })
        },
        updated() {
            if (this.authState !== "signedin") {
                setTimeout(customHideSignUp, delayInMs);
            }
            // (50attempts * 100ms = 5second)
            const maxCountExecutionAttempts = 50;
            const delayInMs = 100;
            let countFunctionCalls = 0;
            function customHideSignUp() {
                try {
                    countFunctionCalls++;
                    let amplifyAuthenticatorWrapperNodeList = document.querySelectorAll("amplify-authenticator");
                    if (!amplifyAuthenticatorWrapperNodeList || !amplifyAuthenticatorWrapperNodeList.length) {
                        if (countFunctionCalls < maxCountExecutionAttempts) {
                            setTimeout(customHideSignUp, delayInMs);
                        }
                        return;
                    }
                    for (let amplifyAuthenticatorWrapper of Array.from(amplifyAuthenticatorWrapperNodeList)) {
                        if (amplifyAuthenticatorWrapper && amplifyAuthenticatorWrapper.shadowRoot) {
                            let amplifySignInNodeList = amplifyAuthenticatorWrapper.shadowRoot.querySelectorAll("amplify-sign-in");
                            if (!amplifySignInNodeList || !amplifySignInNodeList.length) {
                                if (countFunctionCalls < maxCountExecutionAttempts) {
                                    setTimeout(customHideSignUp, delayInMs);
                                }
                                return;
                            }
                            for (let amplifySignForm of Array.from(amplifySignInNodeList)) {
                                if (amplifySignForm && amplifySignForm.shadowRoot) {
                                    let amplifyFormSectionsNodeList = amplifySignForm.shadowRoot.querySelectorAll("amplify-form-section");
                                    if (!amplifyFormSectionsNodeList || !amplifyFormSectionsNodeList.length) {
                                        if (countFunctionCalls < maxCountExecutionAttempts) {
                                            setTimeout(customHideSignUp, delayInMs);
                                        }
                                        return;
                                    }
                                    for (let amplifyFormSection of Array.from(amplifyFormSectionsNodeList)) {
                                        if (amplifyFormSection && amplifyFormSection.childNodes && amplifyFormSection.childNodes.length) {
                                            for (let amplifySectionNode of Array.from(amplifyFormSection.childNodes)) {
                                                let amplifyButtonsNodeList = amplifySectionNode.querySelectorAll("amplify-button");
                                                if (!amplifyButtonsNodeList || !amplifyButtonsNodeList.length) {
                                                    continue;
                                                }
                                                for (let amplifyButton of Array.from(amplifyButtonsNodeList)) {
                                                    if (amplifyButton && amplifyButton.getAttribute("data-test") === "sign-in-create-account-link") {
                                                        let parentSpanWrapper = amplifyButton.parentNode;
                                                        if (parentSpanWrapper.tagName.toLowerCase() === "span") {
                                                            parentSpanWrapper.innerHTML = "";
                                                            countFunctionCalls = maxCountExecutionAttempts;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (countFunctionCalls < maxCountExecutionAttempts) {
                                        setTimeout(customHideSignUp, delayInMs);
                                    }
                                }
                            }
                        }
                    }
                } catch (ex) {
                    console.error(ex);
                }
            }
        },
        data() {
            return {
                user: undefined,
                authState: undefined,
                unsubscribeAuth: undefined
            }
        },
        beforeUnmount() {
            this.unsubscribeAuth();
        },
        methods: {
        }
    }
</script>
GoodLuc commented 3 years ago

Hi. Is this still an issue? It's weird that you have a vue 3 ui component but not the ability to hide sign up or change any other attributes on it.

joshfriend commented 3 years ago

@GoodLuc make sure you are using @aws-amplify/ui-components instead fo @aws-amplify/ui-vue or amplify-vue-ui. That was my problem anyways.

GoodLuc commented 3 years ago

@joshfriend the problem still remains:

Vue 3 DOES NOT allow slot attributes, which is the way to customize the component @aws-amplify/ui-components -> see link, so the Vue 3 aws-amplify-ui component CANNOT be customized in Vue 3, which is strange.

I ended up cloning the repo, modifing it and rebuilding my own version with the defaults I needed.

joshfriend commented 3 years ago

I did a double take after reading your comment just now and realized the project I'm working on didn't migrate to Vue 3 yet, so you're obviously correct 😆

GoodLuc commented 3 years ago

@joshfriend best of luck if you do. Like I said I just cloned the repo and made my own version, setting hideSignup = true as a default and so on. '^^

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.