The plugin doesn't activate in VueJS - vuejs2

I tried to use vue-authenticate in my app, but I've some problems using the plugins' methods. This plugin has as dependency vue-resource, so the first step is installing both packages.
The in main.js file, I import and activate both packages, including the specific configuration for local authentication:
import Vue from 'vue'
import VueResource from 'vue-resource'
import VueAuthenticate from 'vue-authenticate'
// ...
Vue.use(VueResource)
Vue.use(VueAuthenticate, {
baseUrl: 'http://sgc-server.dev',
tokenType: 'Token'
})
Now, in my login component, named Login, create a method, called aLogin to avoid name conflicts:
// ...
methods: {
aLogin: (_credenciales) => {
this.$auth.login(_credenciales).then((_carga) => {
// Ejecutamos la lógica que sigue a un login exitoso
console.log(_carga)
})
}
}
// ..
In this component, credenciales is an object, defined in data() with two properties, username and password. The method aLogin is called in a form on submit event.
<form class="form" #submit.prevent="aLogin(credenciales)">
But nothing happen, and have this in the console.
Login.vue?8031:64 Uncaught TypeError: Cannot read property 'login' of undefined
at VueComponent.aLogin (eval at <anonymous> (app.js:1987), <anonymous>:18:18)
at Proxy.boundFn (eval at <anonymous> (app.js:735), <anonymous>:125:14)
at submit (eval at <anonymous> (app.js:7875), <anonymous>:21:13)
at HTMLFormElement.invoker (eval at <anonymous> (app.js:735), <anonymous>:1657:18)
Why the this.$auth is undefined if it is already registered in main.js? How can activate it properly?
Thanks in advance.

Do not define a method in Vue with a fat arrow function. If you do that, this does not refer to the Vue instance.
Try
methods: {
aLogin: function(_credenciales){
this.$auth.login(_credenciales).then((_carga) => {
// Ejecutamos la lógica que sigue a un login exitoso
console.log(_carga)
})
}
}
See VueJS: why is “this” undefined?

Related

Rethrowing an error causes vue warning in jest test

I've got a vue application which exists of a page component and a nested child component, which makes a async post-request. If the request is failing, an error is thrown, which is propagated to the top component (Page.vue). This top component handles all errors of its child with the errorCaptured-Lifecycle hook. Here is an working example on stackblitz
The mechanism is working fine and no warning is displayed for my app. However, I want to test my child component isolated with jest and vue-test-utils. Therefore, I made a test:
import { mount } from "#vue/test-utils";
import Child from "./Child";
jest.mock("./api", () => ({
createSomething: jest.fn(),
}));
it("creation is erroneous", async () => {
const wrapper = mount(Child);
createSomething.mockImplementation(() => {
throw new Error("error");
});
let createAction = wrapper.find("[data-test-create]");
await createAction.trigger("click");
});
However, because the error is rethrown and never catched by the parent component, there is always a console log statement in my test output:
console.warn
[Vue warn]: Unhandled error during execution of native event handler
at <Child ref="VTU_COMPONENT" >
at <VTUROOT>
How can i solve this? I tried to wrap await createAction.trigger("click"); with try/catch but its not working. Do I need to mock the errorCaptured lifecycle of my parent?
One solution is to set a no-op app.config.errorHandler via the global.config mounting option:
const wrapper = mount(Child, {
global: {
config: {
errorHandler(err) { /* ignore */ },
},
},
})
demo

Vue3 isCustomElement seems not working and vue router clash with custom element

I have VUE3 app with vue-router using third party web components imported as custom elements, I set the isCustomElement option to ignore custom element, but it seems not to be taken into account.
I set the "vue": { "runtimeCompiler": true } in package.json.
I set app.config.isCustomElement = (tag) => tag.startsWith('bdl-') to ignore customElements in main.js
I use web components - custom elements starting with bdl- in About.vue:
<template>
<div class="about">
<h1>This is an about page</h1>
<bdl-fmi></bdl-fmi>
<bdl-range></bdl-range>
<bdl-chartjs-time></bdl-chartjs-time>
</div>
</template>
However, it seems that it's not taken into account and the browser console log contains warning [Vue warn]: Failed to resolve component: bdl-fmi and custom elements fails to render in router view.
Tried VUE2 and the configuration Vue.config.ignoredElements = ['bdl-chartjs'] is working and similar application with vue-router do not try to interpret third party custom elements and renders as expected.
Any thoughts on isCustomElement will be appreciated.
Sample with this issue can be seen at CODESANDBOX: https://codesandbox.io/s/vue-3-router-with-bodylightjs-components-h8v50
The app.config.isCustomElement flag is intended for projects that use the runtime compiler, which could be enabled in a Vue CLI project via the runtimeCompiler flag in vue.config.js:
// vue.config.js
module.exports = {
runtimeCompiler: true,
}
But you could also resolve this without the runtime compiler by removing app.config.isCustomElement, and configuring vue-loader directly:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.compilerOptions = {
...options.compilerOptions,
isCustomElement: tag => tag.startsWith('bdl-')
}
return options
})
}
}
I meet the problem because element-plus icon component not called correctly. I have to import ElementPlusIconsVue in my main.js and global register it like the following:
import * as ElementPlusIconsVue from '#element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
// then I can call the icon in my vue file directly
<Refresh
style="width:30px;cursor: pointer;float: right;"
#click="get_bili"
/>

Is there a way to trigger a vuex mutation on every input in a q-popup-edit component of a q-td in a q-table?

i am working with the q-table in an app with vuex. Adding the popup edit to the table and editing a fields content in the browser, i get these errors and warnings in the console (see below).
The app works as expected, but is throwing those errors, but is throwing these funny error messages. I think it is a necessary learning to not just disable strict mode but to understand what is the right way to do this.
How can i trigger a vuex mutation on user input into this q-popup-edit in a way that the browser will not throw these error messages?
I have tried suppressing the warning which makes no real sense.
I have read the documentation
https://quasar.dev/vue-components/popup-edit
which holds no references to any callback function for on user input
...
<template>
<div class="q-pa-md">
<q-table
title="Bewerber"
:data="data"
:columns="columns"
row-key="id"
binary-state-sort
separator="cell"
selection="single"
:selected.sync="selected"
>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-checkbox dense v-model="props.selected" />
</q-td>
<q-td key="id" :props="props">
{{ props.row.id }}
</q-td>
<q-td key="added" :props="props">
{{ props.row.added }}
<q-popup-edit v-model="props.row.added" buttons #save="saveRow(props.row)">
<q-input type="text" v-model="props.row.added" dense autofocus counter />
</q-popup-edit>
</q-td>
...
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers."
(found in <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
run # vue.runtime.esm.js?2b0e:4564
update # vue.runtime.esm.js?2b0e:4536
notify # vue.runtime.esm.js?2b0e:730
reactiveSetter # vue.runtime.esm.js?2b0e:1055
set # vue.runtime.esm.js?2b0e:1077
callback # list.vue?994d:645
invokeWithErrorHandling # vue.runtime.esm.js?2b0e:1854
invoker # vue.runtime.esm.js?2b0e:2179
invokeWithErrorHandling # vue.runtime.esm.js?2b0e:1854
Vue.$emit # vue.runtime.esm.js?2b0e:3882
emitValueFn # QInput.js?27f9:145
emitValue # QInput.js?27f9:162
onInput # QInput.js?27f9:126
invokeWithErrorHandling # vue.runtime.esm.js?2b0e:1854
invoker # vue.runtime.esm.js?2b0e:2179
original._wrapper # vue.runtime.esm.js?2b0e:6911
vue.runtime.esm.js?2b0e:1888 Error: [vuex] do not mutate vuex store state outside mutation handlers.
at assert (vuex.esm.js?2f62:90)
at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:774)
at Watcher.run (vue.runtime.esm.js?2b0e:4562)
at Watcher.update (vue.runtime.esm.js?2b0e:4536)
at Dep.notify (vue.runtime.esm.js?2b0e:730)
at Object.reactiveSetter [as address_line_1] (vue.runtime.esm.js?2b0e:1055)
at Proxy.set (vue.runtime.esm.js?2b0e:1077)
at callback (list.vue?994d:645)
at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1854)
at VueComponent.invoker (vue.runtime.esm.js?2b0e:2179)
EDIT: (after Guillaume Meral's comment below, thx for pointing out this missing info)
The data prop is set like this:
computed: {
data: function () {
return this.$store.getters['candidate/getCandidates']
}
},
I expect to be able to catch these input events and call a vuex action to mutate the state properly and thereby get rid of the errors / warnings. But there seems to be little documentation about this, maybe i am overseeing something?
This is my first question on Stackoverflow. Please let me know if i need to update my question or specify anything in more detail.
Thanks for your help #community.
**EDIT: ** my first attempted solution was to add setters to the computed property like described in the link posted by Guillaume Meral below.
I have implemented this change, looking like this:
computed: {
data: {
// getter
get: function () {
return this.$store.getters['candidate/getCandidates']
},
// setter
set: function (newData) {
this.$store.dispatch('candidate/updateCandidateList', newData)
}
}
},
with an action
export function updateCandidateList (state, data) {
state.commit('setCandidates', data)
}
and a mutation
export function setCandidates (state, data) {
if (data) {
state.candidates = JSON.parse(JSON.stringify(data))
} else {
state.candidates = null
}
}
and state
export default {
candidates: []
}
Still the warnings persist in the console
[Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers."(found in <Root>)
vue.runtime.esm.js?2b0e:1888 Error: [vuex] do not mutate vuex store state outside mutation handlers.
at assert (vuex.esm.js?2f62:90)
at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:774)
at Watcher.run (vue.runtime.esm.js?2b0e:4562)
at Watcher.update (vue.runtime.esm.js?2b0e:4536)
at Dep.notify (vue.runtime.esm.js?2b0e:730)
at Object.reactiveSetter [as added] (vue.runtime.esm.js?2b0e:1055)
at Proxy.set (vue.runtime.esm.js?2b0e:1077)
at callback (list.vue?994d:93)
at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1854)
at VueComponent.invoker (vue.runtime.esm.js?2b0e:2179)
sidenote: also adding JSON.parse(JSON.stringify(data)) anywhere wont help ^^
I don't get what is wrong here. Let me know if you do, please.
SOLUTION
Mapstate solved the problem for me. It does suppress the errors on every keystroke done in the text input field before hitting the save button.
computed: {
...mapState('candidate', {
data: state => state.candidate
})
},
SOLUTION
Mapstate solved the problem for me. It does suppress the errors on every keystroke done in the text input field before hitting the save button.
computed: {
...mapState('candidate', {
data: state => state.candidate
})
},

How can I spy or mock methods in Vue with sinon?

I'm trying to create a unit test for my app based in Vue and vue-cli with webpack template.
I read Vue documentation, vue-loader, vue-cli and vue-template/webpack (an more!). When I try to make a unit test for my component, I use this.
const Constructor = Vue.extend(MovieList)
vm = new Constructor({
propsData: {
criteria
},
methods: {
fetch: sandbox.spy()
}
}).$mount()
And test this:
expect(vm.fetch).to.be.called
But I get this error:
✗ should be called fetch
TypeError: { [Function: boundFn] _length: 0 } is not a spy or a call to a spy!
at assertCanWorkWith (/home/jmanuelrosa/Developer/personales/vue-course/movues/node_modules/sinon-chai/lib/sinon-chai.js:43:19)
at Assertion. (/home/jmanuelrosa/Developer/personales/vue-course/movues/node_modules/sinon-chai/lib/sinon-chai.js:70:13)
at Assertion.addProperty (/home/jmanuelrosa/Developer/personales/vue-course/movues/node_modules/chai/chai.js:4240:29)
at Context. (webpack:///test/unit/specs/MovieList.spec.js:74:39 <- index.js:14910:39)
Never worked with sinon but doc says:
sinon.spy(vm, "fetch");
expect(vm.fetch).toHaveBeenCalled();
http://sinonjs.org/releases/v2.1.0/spies/
Are you calling fetch upon component created? sometimes you need to manually trigger methods.

angular2 testing, error in ViewUtils when using setBaseTestProviders()

When using the method 'setBaseTestProviders(..)', an error pops up in the console.
We're using angular-2.0.0-rc.1.
The test (test/areas-list.component.spec.ts) is as follows:
import {setBaseTestProviders} from "#angular/core/testing";
import {ADDITIONAL_TEST_BROWSER_PROVIDERS, TEST_BROWSER_STATIC_PLATFORM_PROVIDERS} from '#angular/platform-browser/testing/browser_static';
import {BROWSER_APP_DYNAMIC_PROVIDERS} from '#angular/platform-browser-dynamic';
setBaseTestProviders([
BROWSER_APP_DYNAMIC_PROVIDERS,
ADDITIONAL_TEST_BROWSER_PROVIDERS,
], TEST_BROWSER_STATIC_PLATFORM_PROVIDERS);
describe('test test', () => {
//Not really important
});
When I open the browser, the following error is shown in the console:
zone.js:323 Error: Error: Cannot resolve all parameters for 'ViewUtils'(RootRenderer, undefined #Inject(Token AppId), SanitizationService). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'ViewUtils' is decorated with Injectable.
at NoAnnotationError.BaseException [as constructor] (http://127.0.0.1:8080/node_modules/#angular/core/src/facade/exceptions.js:17:23)
at new NoAnnotationError (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_exceptions.js:217:16)
at _extractToken (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_provider.js:232:15)
at eval (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_provider.js:184:45)
at Array.map (native)
at _dependenciesFor (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_provider.js:184:19)
at resolveReflectiveFactory (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_provider.js:72:24)
at resolveReflectiveProvider (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_provider.js:96:97)
at Array.map (native)
at Object.resolveReflectiveProviders (http://127.0.0.1:8080/node_modules/#angular/core/src/di/reflective_provider.js:104:31)
Evaluating http://127.0.0.1:8080/test/areas-list.component.spec.js
Error loading http://127.0.0.1:8080/test/areas-list.component.spec.js
Does somebody know what the problem is? Thanks in advance!
Is there any specific case you're trying to achieve with browser static?
Here is the basic config:
import { setBaseTestProviders } from '#angular/core/testing';
import {
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,
TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
} from '#angular/platform-browser-dynamic/testing';
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);