Reputation: 14961
I have a vue component with
<form @keydown="console.error($event.target.name);">
gives
app.js:47961 [Vue warn]: Property or method "console" is not defined on the instance but referenced during render.
window.console
doesn't work either
What is the proper way to use console and window in a template to debug?
Upvotes: 72
Views: 217424
Reputation: 51
It has been fixed in Vue 3.3, see the GitHub issue. You can use console in the template.
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<h1>{{ count }}</h1>
<button @click="console.log(++count)"</button>
</template>
This post has some background reading on it.
Upvotes: 1
Reputation: 11417
With Vue ^3.3, you can now use console
directly in the template:
<template>
<!-- just works, no more `console` doesn't exist -->
<button @click="console.log">Log</button>
</template>
If using Vue prior to 3.3, do:
const app = createApp(App)
app.config.globalProperties.console = console
If also using TypeScript:
// types.d.ts
export {}
declare module 'vue' {
interface ComponentCustomProperties {
console: Console
}
}
If using Vue 2, do:
Vue.prototype.console = console
Use console.*
inside the template:
<h1>{{ console.log(message) }}</h1>
To not interfere with the rendering, use console.*
with ??
(or ||
if using Vue 2, since ??
is not supported in the Vue 2 template):
<h1>{{ console.log(message) ?? message }}</h1>
Upvotes: 19
Reputation: 684
I found this template code that may be useful, https://gist.github.com/jensendarren/11afda8dee3171a192df3443f7a1508a
<!--Make sure to install @vue/cli-service-global first-->
<!--Serve this up using `vue serve` at the command line-->
<!--Details here: https://cli.vuejs.org/guide/prototyping.html -->
<template>
<div>
<h1>{{name}}</h1>
<b>Logging To Vue Component? <span>{{logging}}</span></b>
<br />
<button @click="testLog">Test Log</button>|<button @click="testWarn">Test Warn</button>|<button @click="toggleLogging">Toggle Logging</button>
<hr/>
<p v-for="(log, i) in logs" :key="i" :style="log.style" class="linebreaks" >{{log.message}}</p>
</div>
</template>
<script>
export default {
data() {
return {
name: 'Console Log Prototype',
logs: [],
o_log: null,
o_warn: null,
logging: true
}
},
methods: {
testLog() {
var var1 = 'Darren'
var var2 = 'Jensen'
console.log('in testLog()')
console.log('This should be\non a new line')
console.log(`First name: ${var1}, last name: ${var2}`);
console.log('string 1', 'string 2', var1, var2)
console.log(`%c[routeTo] ${var1}`, "color: #00b4e8;")
},
testWarn() {
console.warn('in testWarn()')
},
toggleLogging() {
if(this.logging) {
// Disable logging
console.log = this.o_log
console.warn = this.o_warn
this.clearLogs();
} else {
// Activate logging
this.overrideLogging();
}
this.logging = !this.logging
},
clearLogs() {
this.logs = []
},
overrideLogging() {
let self = this;
this.o_log = console.log
this.o_warn = console.warn
function customLog(...msg) {
var entry = parseMsgArray(msg)
self.logs.push(entry)
self.o_log.apply(console, arguments)
}
function customWarn(msg) {
var entry = {color: 'yellow', message: msg}
self.logs.push(entry)
self.o_warn.apply(console, arguments)
}
function parseMsgArray(msgArray) {
var entry;
if(msgArray[0].includes('%c')) {
// 2nd param will contain styles to apply
var applyStyle = msgArray[1]
var msg = msgArray[0].replace('%c', '')
entry = {style: applyStyle, message: msg }
} else {
entry = {style: {color: 'black', background: 'pink'}, message: msgArray.join(' ')}
}
return entry
}
console.log = customLog;
console.warn = customWarn;
}
},
created() {
this.overrideLogging();
}
}
</script>
<style scoped>
.linebreaks {
white-space:pre;
}
</style>
Upvotes: 0
Reputation: 399
For Vue 3, SFC Composition API, you have to define a function and call console
or alert
inside that function
<script setup>
import Child from "./Child.vue";
function notify(message) {
alert(message);
}
</script>
<template>
<Child @some-event="notify('child clicked')" />
</template>
Upvotes: 1
Reputation: 41
You can use computed property or methods for this case. If you need to code it as javascript in the Vue template. you have to define console in the data.
Please check the code below.
data(){
return {
selected :"a",
log : console.log
}
}
<span>{{log(selected)}}</span>
This will make functionality of console.log available, while resolving the template.
Upvotes: 2
Reputation: 6501
You can use $el.ownerDocument.defaultView.console.log()
inside your template
Pro: Doesn't require any component changes
Con: Ugly
Upvotes: 22
Reputation: 111
Also if you want to access console from {{ }} you can use global mixin:
Vue.mixin({
computed: {
console: () => console
}
})
Upvotes: 11
Reputation: 90277
Simplest way of providing global objects to the template is to place them in computed
, like this:
console: () => console
. Same goes for window
,
computed: {
console: () => console,
window: () => window,
}
See it here.
Upvotes: 44
Reputation: 717
You can use this.console instead console or wrap call to console in a method, i am using eslint config with rule 'no-console': 'off'
Upvotes: 2
Reputation: 313
I'd make a getter for console template variable:
get console() { return window.console; }
Upvotes: 1
Reputation: 4132
If you want to run it inline instead of using a method, just add this
to the form:
Codepen: https://codepen.io/x84733/pen/PaxKLQ?editors=1011
<form action="/" @keydown="this.console.log($event.target.name)">
First: <input type="text" name="fname"><br>
Second: <input type="text" name="fname2"><br>
</form>
But it'd be better to use a method instead of running functions inline, so you have more control over it:
<!-- Don't forget to remove the parenthesis -->
<form action="/" @keydown="debug">
First: <input type="text" name="fname"><br>
Second: <input type="text" name="fname2"><br>
</form>
...
methods: {
debug (event) {
console.log(event.target.name)
}
}
Upvotes: 29