I would like to use the AWS Amplify Authenticator in a js vue2 app. The manual that I used can be found here: https://github.com/aws-amplify/amplify-ui/tree/legacy/legacy/amplify-ui-vue#recommended-usage
But I end up getting an Object(...) is not a function error.
TypeError: Object(...) is not a function
at Module.eval (index.js?2bbc:22:1)
at eval (index.js:12544:30)
at Module../node_modules/#aws-amplify/ui-vue/dist/index.js (sign-in.js:167:1)
at __webpack_require__ (app.js:859:30)
at fn (app.js:151:20)
at eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/pages/auth/SignInPage.vue?vue&type=script&lang=js&:2:77)
at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/pages/auth/SignInPage.vue?vue&type=script&lang=js& (sign-in.js:179:1)
at __webpack_require__ (app.js:859:30)
at fn (app.js:151:20)
at eval (SignInPage.vue?0642:1:1)
The page SignInPage.vue looks like this:
<template>
<div>
<amplify-authenticator />
</div>
</template>
<script>
import '#aws-amplify/ui-vue'
import { onAuthUIStateChange } from '#aws-amplify/ui-components'
export default {
name: 'SignInPage',
created() {
this.unsubscribeAuth = onAuthUIStateChange((authState, authData) => {
this.authState = authState
this.user = authData
})
},
data() {
return {
user: undefined,
authState: undefined,
unsubscribeAuth: undefined,
}
},
beforeDestroy() {
this.unsubscribeAuth()
},
}
</script>
I tried both the example on the top of the page, as the bottom examples (migrated section), both ending up with the same error. Can anybody help me out?
Update 1:
SignInPage.vue
<template>
<div>
<authenticator />
</div>
</template>
<script>
import { Authenticator } from '#aws-amplify/ui-vue'
import '#aws-amplify/ui-vue/styles.css'
export default {
name: 'SignInPage',
components: { Authenticator },
}
</script>
package.json
"dependencies": {
"#apollo/client": "^3.3.9",
"#aws-amplify/ui-vue": "^2.3.11",
"#vue/apollo-composable": "^4.0.0-alpha.12",
"#vue/composition-api": "^1.0.0-rc.2",
"aws-amplify": "^4.3.20",
"aws-appsync": "^4.0.3",
"vue": "^2.6.11",
}
After a lot of tries the following seems to solve it, with the help of this page: https://docs.amplify.aws/lib/auth/getting-started/q/platform/js/#option-1-use-pre-built-ui-components
Steps I have taken:
uninstall the all the aws-amplify packages
(re-)add aws-amplify #aws-amplify/ui-components packages
remove the #aws-amplify related imports from the SignIn page
add the following to the main.js
import { applyPolyfills, defineCustomElements } from '#aws-amplify/ui-components/loader';
applyPolyfills().then(() => {
defineCustomElements(window);
});
Vue.config.ignoredElements = [/amplify-\w*/];
SignInPage.vue
<template>
<div>
<amplify-authenticator />
</div>
</template>
<script>
export default {
name: 'SignInPage',
}
</script>
Related
I'm having an issue with rendering quasar components in the storybook with Vue and Quasar. I suspect it's not finding the quasar tags in the story. I just followed these steps to set up the project https://quasar.dev/start/vue-cli-plugin and then I ran npx sb init to set up the storybook in my app. After all, compilation works fine but when I view my story on the storybook screen I got the below error that appears. You check the screen here https://prnt.sc/1qd3ywr
I tried all possible solutions but none had worked. Any suggestions would be appreciated.
TypeError: Cannot read property 'screen' of undefined
at setup (http://localhost:6006/vendors~main.iframe.bundle.js:89474:322262)
at callWithErrorHandling (http://localhost:6006/vendors~main.iframe.bundle.js:37183:22)
at setupStatefulComponent (http://localhost:6006/vendors~main.iframe.bundle.js:44151:29)
at setupComponent (http://localhost:6006/vendors~main.iframe.bundle.js:44107:11)
at mountComponent (http://localhost:6006/vendors~main.iframe.bundle.js:42108:13)
at processComponent (http://localhost:6006/vendors~main.iframe.bundle.js:42083:17)
at patch (http://localhost:6006/vendors~main.iframe.bundle.js:41698:21)
at componentEffect (http://localhost:6006/vendors~main.iframe.bundle.js:42220:21)
at reactiveEffect (http://localhost:6006/vendors~main.iframe.bundle.js:36022:24)
at effect (http://localhost:6006/vendors~main.iframe.bundle.js:35997:9)
Here is my story for the quasar component: (quasar.stories.js)
import { QLayout, QPageContainer, QPage, QSelect, QBtn } from 'quasar'
export default {
title: 'Quasar'
}
export const Components = () => ({
title: 'QuasarComponents',
components: { QLayout, QPageContainer, QPage, QSelect, QBtn },
template: `<q-layout>
<q-page-container>
<q-page class="full-height full-width justify-center items-center q-pa-xl">
<div class="col-auto">
<q-input v-model="name" label="Full name" />
<q-select v-model="role" :options="options" label="User Role" />
</div>
</q-page>
</q-page-container>
</q-layout>`,
data () {
return {
name: null,
role: 'User',
options: ['Admin', 'Supervisor', 'User']
}
}
})
main.js
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
]
}
preview.js
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
This looks like GitHub issue #7263, which is caused by an app extension.
One user discovered a solution:
em-qui is an app-extension that was also declaring quasar as a devDependency (for IDE support...), though on the same version this was somehow causing a confict:
{
"devDependencies": {
"graphql-tag": "^2.10.3",
"quasar": "^1.12.6"
},
}
So I had to separate the two by declaring it in peerDependencies in the app extension:
{
"devDependencies": {
"graphql-tag": "^2.10.3"
},
"peerDependencies": {
"quasar": "^1.12.6"
}
}
and the error went away.
It seems that Vue Meta has been upgraded to handle Vue.js 3 with a new npm package called vue-3-meta
Before Vue.js 3, it was easy to use vue-meta by adding it to the Vue instance:
import Vue from 'vue'
import VueMeta from 'vue-meta'
Vue.use(VueMeta, {
// optional pluginOptions
refreshOnceOnNavigation: true
})
However in Vue.js 3, there is no Vue instance; and instead you create the app by running createApp like such:
const app = createApp(App);
const router = createVueRouter();
app.use(router);
// need to make app use Vue-Meta here
I cannot find any documentation for vue-3-meta. import VueMeta from 'vue-meta' no longer works.
How do I import the vue-3-meta plugin properly and use it with app like in prior versions?
Disclaimer: vue-meta v3 is still in alpha!
This was the minimal implementation I needed to get started:
Update vue-meta to v3 (in package.json)
- "vue-meta": "^2.4.0",
+ "vue-meta": "^3.0.0-alpha.7",
...or with yarn:
yarn add vue-meta#alpha
Add metaManager to Vue app
import { createMetaManager } from 'vue-meta'
const app = createApp(App)
.use(router)
.use(store)
.use(createMetaManager()) // add this line
await router.isReady()
app.mount('#app')
Add <metainfo> to App.vue <template> (this is also where I set a "title template")
<template>
<metainfo>
<template v-slot:title="{ content }">{{ content ? `${content} | SITE_NAME` : `SITE_NAME` }}</template>
</metainfo>
<header />
<router-view />
<footer />
</template>
Set default meta in App.vue <script>
Vue 3 vanilla:
import { useMeta } from 'vue-meta'
export default {
setup () {
useMeta({
title: '',
htmlAttrs: { lang: 'en', amp: true }
})
}
}
or with vue-class-component:
import { setup, Vue } from 'vue-class-component'
import { useMeta } from 'vue-meta'
export default class App extends Vue {
meta = setup(() => useMeta({
title: '',
htmlAttrs: { lang: 'en', amp: true }
})
}
Override meta in each component
Vue 3 vanilla:
import { useMeta } from 'vue-meta'
export default {
setup () {
useMeta({ title: 'Some Page' })
}
}
or with vue-class-component:
import { computed } from '#vue/runtime-core'
import { setup, Vue } from 'vue-class-component'
import { useMeta } from 'vue-meta'
export default class SomePage extends Vue {
meta = setup(() => useMeta(
computed(() => ({ title: this.something?.field ?? 'Default' })))
)
}
See also:
"Quick Usage" (vue-meta next branch)
Vue Router Example (vue-meta next branch)
In addition to the previous answers, I also needed to add a transpileDependency in my vue.config.js, as I was using vue-cli:
module.exports = {
transpileDependencies: ['vue-meta']
}
Else, I would get the error:
error in ./node_modules/vue-meta/dist/vue-meta.esm-browser.min.js
Module parse failed: Unexpected token (8:7170)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
Thanks to this thread for pointing me to this: https://stackoverflow.com/a/65844988/3433137
metaManager is a MetaManager instance created from createMetaManager() of vue-meta.
Based on the Vue 3 + Vue Router example for vue-meta, here's an example usage:
import { createApp } from 'vue'
import { createMetaManager, defaultConfig, resolveOption, useMeta } from 'vue-meta'
const decisionMaker5000000 = resolveOption((prevValue, context) => {
const { uid = 0 } = context.vm || {}
if (!prevValue || prevValue < uid) {
return uid
}
})
const metaManager = createMetaManager({
...defaultConfig,
esi: {
group: true,
namespaced: true,
attributes: ['src', 'test', 'text']
}
}, decisionMaker5000000)
useMeta(
{
og: {
something: 'test'
}
},
metaManager
)
createApp(App).use(metaManager).mount('#app')
I'm using javascript. I used Vue and traditional html to write a reactive single page app, and I want to port it over to vue cli. I have several js files. One has a function in it that I want to call using Vue single file components. One of the js files is called 'controls.js'. One is called 'v.js'. The v.js file has a vue instance. I want to run a function in control.js from the v.js file.
//error msg
[Vue warn]: Error in v-on handler: "TypeError: formSubmitMessage is not a function"
found in
---> <Message> at src/components/Message.vue
<Appx> at src/App.vue
<Root>
warn # vue.runtime.esm.js?2b0e:619
logError # vue.runtime.esm.js?2b0e:1884
globalHandleError # vue.runtime.esm.js?2b0e:1879
handleError # vue.runtime.esm.js?2b0e:1839
invokeWithErrorHandling # vue.runtime.esm.js?2b0e:1862
invoker # vue.runtime.esm.js?2b0e:2179
original._wrapper # vue.runtime.esm.js?2b0e:6917
vue.runtime.esm.js?2b0e:1888
TypeError: formSubmitMessage is not a function
at Vue.useFormSubmitMessage (v.js?e9d2:118)
at VueComponent.useFormSubmitMessage (App.vue?234e:202)
at click (eval at ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"9216e95a-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/Message.vue?vue&type=template&id=61d2d687& (app.js:1082), <anonymous>:33:42)
at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1854)
at HTMLButtonElement.invoker (vue.runtime.esm.js?2b0e:2179)
at HTMLButtonElement.original._wrapper (vue.runtime.esm.js?2b0e:6917)
logError # vue.runtime.esm.js?2b0e:1888
globalHandleError # vue.runtime.esm.js?2b0e:1879
handleError # vue.runtime.esm.js?2b0e:1839
invokeWithErrorHandling # vue.runtime.esm.js?2b0e:1862
invoker # vue.runtime.esm.js?2b0e:2179
original._wrapper # vue.runtime.esm.js?2b0e:6917
// v.js
import Vue from "vue";
import appx from "../App.vue";
require("./populate.js");
const {formSubmitMessage, preview_image_msg} = require ('./populate.js');
export function doLoad() {
let visibility = new Vue({
el: '#app',
render: h => h(appx),
data() {
return {
login: false,
register: false,
newsfeed: false,
home: true,
banner: true,
form_message: false,
form_exercise: false,
form_workout: false
};
},
mounted() {
console.log("mounted");
},
methods: {
classOption: function (i) {
const x = Boolean(i);
if (x === true) return 'visi';
else return 'invis';
},
// this is only part of list of functions.
useFormSubmitMessage: function () {
formSubmitMessage(); //<<-- this does not work.
}
}
});
}
//main.js
import Vue from "vue";
import './../node_modules/bulma/css/bulma.css';
import "./../node_modules/#fortawesome/fontawesome-free/js/all.js"
import '#/assets/bulma.css';
require("./js/v.js");
import { doLoad } from "./js/v.js";
doLoad();
//App.vue
<template>
<div id="appx">
<message
:newsfeed="newsfeed"
:banner="banner"
:login="login"
:register="register"
:home="home"
:form_message="form_message"
:form_exercise="form_exercise"
:form_workout="form_workout"
:focusRegister="focusRegister"
:focusNews="focusNews"
:focusReset="focusReset"
:focusLogin="focusLogin"
:focusFormMessage="focusFormMessage"
:useFormSubmitMessage="useFormSubmitMessage"
></message>
</div>
</template>
<script>
import "./../node_modules/bulma/css/bulma.css";
import "#/assets/bulma.css";
import bannercomponent from "./components/Banner.vue";
import feedcontainer from "./components/FeedContainer.vue";
import register from "./components/Register.vue";
import home from "./components/Home.vue";
import login from "./components/Login.vue";
import message from "./components/Message.vue";
import { visibility, newsfeed, banner } from "./js/v.js";
const {formSubmitMessage} = require ('./js/populate.js');
export default {
name: "appx",
data() {
return {
login: this.$root.login,
register: this.$root.register,
home: this.$root.home,
form_message: this.$root.form_message,
form_exercise: this.$root.form_exercise,
form_workout: this.$root.form_workout,
newsfeed: this.$root.newsfeed,
banner: this.$root.banner,
};
},
components: {
bannercomponent: bannercomponent,
feedcontainer: feedcontainer,
register: register,
home: home,
login: login,
message: message
},
mounted() {
console.log("appx");
},
methods: {
classOption: function (i) {
const x = Boolean(i);
if (x === true) return "visi";
else return "invis";
},
copyVals: function() {
this.login = this.$root.login;
this.register = this.$root.register;
this.home = this.$root.home;
this.form_message = this.$root.form_message;
this.form_exercise = this.$root.form_exercise;
this.form_workout = this.$root.form_workout;
this.newsfeed = this.$root.newsfeed;
this.banner = this.$root.banner;
},
useFormSubmitMessage: function () {
this.$root.useFormSubmitMessage();
this.copyVals();
}
},
};
</script>
// controls.js
import Vue from "vue";
require("./v.js");
import { subtreeStr, setMessage, insertFeed, setExercise } from './populate.js';
import { focusNews } from "./v.js";
export function formSubmitMessage() {
console.log("here 1");
//do some things here that are not listed.
}
//Message.vue
<template>
<!-- start inputform for message -- some listing has been removed -->
<button class="button is-primary" #click="useFormSubmitMessage();">Submit</button>
<input class="file-input is-primary" type="file" name="resume" id="pic-button" ref="picButton" #change="preview_image_msg($event)" multiple>
</template>
<script>
export default {
name: "message",
data: () => ({
}),
props: {
newsfeed: Boolean,
focusFormMessage: Function,
form_message: Boolean,
useFormSubmitMessage: Function,
},
};
</script>
I don't know the proper way to include a function from another file.
It looks like formSubmitMessage is defined as a named export in controls.js, so use a named import for it:
import { formSubmitMessage } from './controls.js'
You are mixing the use of require and import to load modules but it's preferred to stick with one, probably imports, with Vue CLI.
Code in the file:
<template>
<component v-bind:is="bbc"></component>
</template>
<script>
import bbc from './bbc.vue';
export default {
name: 'ShowRoom2',
};
</script>
./bbc.vue
<script>
export default {
name: 'bbc',
props: {
msg: String,
},
mounted() {
console.log('bbc is mounted');
},
render() {
if (this.func) this.func();
return (
<div class="bbcMyClass">
<h1>bbc: <span>Pal</span> <span>{this.msg}</span></h1>
</div>
)
}
};
</script>
To reproduce
git clone git#github.com:adamchenwei/vue-hoc-playground.git
go to src/components/ShowRoom2.vue
yarn install && yarn serve
observe error in the local browser
Yes, the scope in the template is not the same as the script scope. If you need some data, you need to declare it inside the 'component' definition part of the code. For your case, I guess the 'data' property should work
import bbc from './bbc.vue';
export default {
name: 'ShowRoom2',
data() {
return {
bbc: bbc,
};
},
};
However, the template part of your code also looks weird. Could you explain what you're trying to do ?
I am learning (tinkering with) ES6 modules and Vue.js, single file components (SFC). I built my project with the Vue CLI via the webpack-simple template. I get an error "TypeError: Cannot read property 'name' of undefined" at the line with "settings.mainAlarm.name". "npm run dev" does not throw any errors so I believe the build step is finding (and perhaps ignoring) the settings.js file. What is the best way to import reusable JavaScript into a Vue SFC?
Root.vue file:
<template>
<div id="app">
<h1>{{ msg }}</h1>
<h4>{{ alarmName }}</h4>
</div>
</template>
<script>
//const settings = mainAlarm;
import settings from './lib/settings.js'
export default {
name: 'app',
data () {
return {
msg: 'Welcome to Blah Blah Blah!',
alarmName: settings.mainAlarm.name
}
}
}
//console.log(this.alarmName);
</script>
<style>
</style>
./lib/settings.js file:
export default function () {
var rtn = {
mainAlarm: {
name: "overdueCheckAlarm",
info: { delayInMinutes: .01, periodInMinutes: .25 }
},
notificationAudioFile: "ache.mp3",
baseUrl: "www.xxx.com/xx/xxxx-xxx/"
}
return rtn;
}
Either your settings file should look like this
export default {
mainAlarm: {
name: "overdueCheckAlarm",
info: { delayInMinutes: .01, periodInMinutes: .25 }
},
notificationAudioFile: "ache.mp3",
baseUrl: "www.xxx.com/xx/xxxx-xxx/"
}
in which case, your component will work as is, or your component should look like this and you can leave the settings file alone
<script>
import settings from './lib/settings.js'
// settings.js exports a function as the default, so you
// need to *call* that function
const localSettings = settings()
export default {
name: 'app',
data () {
return {
msg: 'Welcome to Blah Blah Blah!',
alarmName: localSettings.mainAlarm.name
}
}
}
</script>
I expect it's the first option you really want (I'm not sure why you would want a unique settings object every time you use settings, which is what the code in your question would do).