Method not changing variable - javascript

I'm creating a app that will be accessing the user's webcam. I want to the change the error variable to the error message if navigator.getUserMedia fails. This should outputting the error message, but instead it's outputting stream. I'm very new to Vue so pardon me if I'm missing something very obvious
my code is as follows
<template>
<div class="">
<h1 v-if="error === null">
Stream
</h1>
<h1 v-else>
{{ error }}
</h1>
</div>
</template>
<script>
export default {
data () {
return {
error: null
}
},
methods: {
setUnsupported () {
this.error = 'Your browser does not support video :('
}
},
ready () {
this.setUnsupported()
if (navigator.getUserMedia) {
} else {
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

If you are using Vue 2.0, ready has been replaced with mounted. Please check the documentation here.
....
mounted () {
this.setUnsupported()
}
....

Related

v-for loop error when updating data - DOMException- Failed to execute 'insertBefore'

I write a navigation component based on vue and ant-design-vue. the LectureNavigation.vue file is like this:
<template>
<div id="navigation-button">
<a-button type="primary" style="width: 62px;
height: 40px;" #click="toggleCollapsed">
<MenuUnfoldOutlined v-if="collapsed" />
<MenuFoldOutlined v-else />
</a-button>
</div>
<div id="expand">
<a-layout-sider width="220px" style="background: #fff">
<a-menu mode="inline" theme="dark" :inline-collapsed="collapsed" v-model:openKeys="openKeys">
<a-menu-item v-for="(item, index) in get_lecture_index()" :key="item[0]">
<template #icon>
<MailOutlined />
</template>
<router-link :to="'/lecture/' + item[1]">{{index}} -{{ item[2] }}</router-link>
</a-menu-item>
</a-menu>
</a-layout-sider>
</div>
</template>
<script>
import { stat_instance } from "#/utils/request";
import router from "#/router/index";
import { defineComponent, reactive, toRefs, watch, onMounted } from "vue";
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
// PieChartOutlined,
MailOutlined,
// DesktopOutlined,
// InboxOutlined,
// AppstoreOutlined,
} from "#ant-design/icons-vue";
export default defineComponent({
data() {
return {
$router: router,
lecture_index: [
["0", "lks", "中华小当家"],
["1", "lks", "中华小当家"],
["2", "fefe", "美美睡一觉"]],
};
},
methods: {
get_lecture_index() {
return this.lecture_index;
}
},
created() {
stat_instance({
url: "/stat_api/get_lecture_index",
})
.then((response) => {
this.lecture_index = response.data.detail);
console.log("lecture_index: ", response);
console.log("lecture_index: ", this.lecture_index);
})
.catch(() => {
console.log("### Failed to request navigation file.");
});
},
components: {
// PieChartOutlined,
MailOutlined,
MenuUnfoldOutlined,
MenuFoldOutlined,
// DesktopOutlined,
// InboxOutlined,
// AppstoreOutlined,
},
});
</script>
<style lang="less">
#navigation-button {
z-index: 20;
display: block;
position: fixed;
top: 10px;
left: 9px;
}
#expand {
z-index: 9;
position: static;
width: 200;
}
#media screen and (max-width: 800px) {
#expand {
position: fixed;
display: none;
}
}
#media screen and (min-width: 801px) {
#navigation-button {
display: none;
}
}
</style>
but the webpage could only render the lecture_index in data method, which contains only 3 items just as the code above. It can not render the response data by a http request in the created method, which contains 8 items in the Array.
And when executing, the chrome reported an error:
Uncaught (in promise) DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
the whole project is as Jionlp_online, when you deploy this project, type the http://ip:port/lecture/entropy_theory_basics could see this error page.
So, How to successfully render the data by the http requests more than 3?
You have two root elements in you tag, wrap it in a seperate div tag so there is only one root element.
Try this:
<template>
<div>
<div id="navigation-button">
...
</div>
<div id="expand">
...
</div>
<div>
</template>

pass emit click to parent in slot element to run function in parent vue 3 slot option api

greeting king,
I'm trying to emit click from child(todoitem.vue) element that contains button and slot in this component to parent(app.vue) that will run a method in parent. For example now when I click edit button then method in parent editable() will run and when I click delete button then run method of deletable() in parent. How to approach this. I had tried to pass using v-slot but it only send variable also try emit but failed to emit. I'm totally new to vue..thanks
parent(app.vue)
<template>
<div>
<todolist>
<todoitem v-for="each in a" :key="each.list">
{{each.list}}
</todoitem>
</todolist>
<todolist>
<todoitem v-for="each in b" :key="each.list">
{{each.list}}
</todoitem>
</todolist>
</div>
</template>
<script>
import todolist from "./components/todolist.vue";
import todoitem from "./components/todoitem.vue";
export default {
name: "App",
data(){
return{
a:[
{list:"AAAA"},
{list:"BBBB"},
{list:"CCC"},
],
b:[
{list:"DDDD"},
{list:"EEEE"},
{list:"FFFF"},
],
}
},
components: {
todolist,
todoitem
},
methods:{
editable(){
console.log('editabel')
},
deletable(){
console.log('deletable')
}
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
child(todoitem)
<template>
<slot></slot>
<button #click="test">Edit</button>
<button #click="test2">delete</button>
</template>
<script>
export default {
name: "todoitem",
method:{
test(){
console.log('edit click')
this.$emit('edit-item')
},
test2(){
console.log('delete click')
this.$emit('del-item')
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
todolist
<template>
<slot></slot>
<div>
</div>
</template>
<script>
export default {
name: "todolist",
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
Basically it's structured like this - just put an emit with the function-name and the paramters inside of one of your methods like this:
Child.vue
this.$emit("Your_Function_Name", Parameter_1, Parameter_2);
Than go to your parent.vue call your emitted function and use it inside your methods of the parent.vue:
Parent.vue
<template>
...
<Child #Your_Function_Name="Your_Function_Name">
...
</template>
<script>
methods: {
Your_Function_Name(Parameter_1, Parameter_2) {
console.log(Parameter_1, Parameter_2)
}
}
</script>
Hopefully this helps you out!

Vue 2 event listener on component root

I'm trying to capture an event on the component root node, but the following does not work. I don't want to just listen on a node in the component. I want to be able to click on any element and then hit backspace to remove it. The code below is a basic example of how I setup my code.
<template>
<div v-on:keydown.delete="delete()">
<img id="image" src="..." v-on:click="set_active()">
</div>
</template>
<script>
export default {
return {
data() {
active: ''
},
methods: {
delete(){
delete this.$refs[this.active][0];
},
set_active() {
this.active = event.target.getAttribute('id');
}
}
}
}
</script>
After doing some tests, here is what I discovered:
Having a method called delete won't work. I don't know why, the question remains unanswered here. Rename it to remove, for example.
When trying to catch keyboard events on a div, you may need to add a tabindex attribute for it to work. (See here)
Interactive demo
Vue.component('my-component', {
template: '#my-component',
data() {
return {
images: [
"https://media.giphy.com/media/3ohs7KtxtOEsDwO3GU/giphy.gif",
"https://media.giphy.com/media/3ohhwoWSCtJzznXbuo/giphy.gif",
"https://media.giphy.com/media/8L0xFP1XEEgwfzByQk/giphy.gif"
],
active: null
};
},
methods: {
set_active(i) {
this.active = i;
},
remove() {
if (this.active !== null) {
this.images = this.images.filter((_, i) => i !== this.active);
this.active = null;
}
}
}
});
var vm = new Vue({
el: '#app'
});
div {
outline: none; /* Avoid the outline caused by tabindex */
border: 1px solid #eee;
}
img {
height: 80px;
border: 4px solid #eee;
margin: .5em;
}
img:hover {
border: 4px solid #ffcda9;
}
img.active {
border: 4px solid #ff7c1f;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>
<div id="app">
<my-component></my-component>
</div>
<template id="my-component">
<div #keydown.delete="remove" tabindex="0">
<img
v-for="(img, i) in images"
:key="i"
:src="img"
:class="{ active: active === i }"
#click="set_active(i)"
/>
</div>
</template>

How to redirect from /pages to layouts/error.vue?

I have created a error.vue file within the layouts folder which should show the UI for a 400, 404, 410 and 500 error. But, it is not showing the ones I created, it is still showing the default NuxtServerError page.
So, my question is how can I show my created UI within a page.
Below is the code that I am using within the layouts/error.vue
HTML:
<template>
<div class="error-container">
<div class="error-content" v-if="error.statusCode === 404">
<div>
<h1>Sorry, the page you were looking for doesn't exist.</h1>
<p>You can return to our <nuxt-link to="/">home page</nuxt-link> or contact us if you can't find what you are looking for.</p>
</div>
<img src="~/assets/Images/404.png">
</div>
<div class="error-content" v-if="error.statusCode === 400">
<div>
<h1>Sorry, the page you are looking for doesn't exist anymore.</h1>
<p>You can return to our <nuxt-link to="/">home page</nuxt-link> or contact us if you can't find what you are looking for.</p>
</div>
<img src="~/assets/Images/404.png">
</div>
<div class="error-content" v-if="error.statusCode === 410">
<div>
<h1>Sorry, the page you are looking for has been deleted.</h1>
<p>You can return to our <nuxt-link to="/">home page</nuxt-link> or contact us if you can't find what you are looking for.</p>
</div>
<img src="~/assets/Images/404.png">
</div>
<div class="error-content" v-if="error.statusCode === 500">
<div>
<h1>Sorry, the page you were looking for doesn't exist.</h1>
<p>You can return to our <nuxt-link to="/">home page</nuxt-link> or contact us if you can't find what you are looking for.</p>
</div>
<img src="~/assets/Images/404.png">
</div>
</div>
</template>
Javascript:
<script>
export default {
head() {
return {
title: 'Lost?'
}
},
props: ['error'],
layout: 'error'
}
</script>
CSS:
<style scoped>
.error-container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.error-content {
width: 90%;
max-width: 800px;
margin: auto;
display: grid;
grid-template: auto / auto 200px;
grid-column-gap: 10px;
text-align: center;
}
.error-content > div {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.error-content > div > h1 {
font-size: 30px;
margin: 0;
}
.error-content > img {
width: 200px;
}
a {
text-decoration: unset;
color: var(--color-tpBlue);
}
</style>
Many thanks in advance!
Redirect to error layout does not happen automatically. Instead, redirect should be done in relevant hooks or methods of your application. It is done by calling error method available in Nuxt context with statusCode and message props passed, which will replace page with with content of layout/error.vue and will respond with HTTP status provided as a statusCode prop.
Here is an example of handling errors inside asyncData:
export default {
async asyncData ({ params, error }) {
try {
const { data } = await axios.get(`https://my-api/posts/${params.id}`)
return { title: data.title }
} catch (e) {
error({ statusCode: 404, message: 'Post not found' })
}
}
}
As a complement to #aBiscuit answer:
For the ones who want to redirect to the error page in another context than asyncData in your component, you can access the error function in this.$nuxt.error.

Polymer add Html tags with properties

My Polymer element displays some properties it gets passed as attributes. The content property may contain some html tags like <br> or <p>. The problem I'm facing with, is, that Polymer doesn't add the tags to the DOM tree, instead it prints them like normal text. Is there a way to force "DOM tree adding"?
The whole element:
<link rel="import" href="paper-toolbar/paper-toolbar.html">
<link rel="import" href="iron-collapse/iron-collapse.html">
<link rel="import" href="paper-material/paper-material.html">
<dom-module id="card-element" is="auto-binding">
<style>
#contentWrapper {
padding: 10px 15px;
}
#toolbar {
--paper-toolbar-background: #607D8B;
--paper-toolbar: {
font-size: 125%;
opacity: 0.9;
};
}
.maxWidth {
width: 100%;
}
</style>
<template>
<paper-material elevation="2" class="maxWidth" id="card" animatedShadow="1">
<paper-material elevation="1" class="maxWidth">
<paper-toolbar on-click="toggleCollapse" id="toolbar" justify="justified">
<span class="title">{{convertedDate}}</span><span class="title">{{fach}}</span>
</paper-toolbar>
</paper-material>
<iron-collapse id="collapse">
<div id="contentWrapper">
<span>{{content}}</span>
</div>
</iron-collapse>
</paper-material>
</template>
<script>
Polymer({
is: "card-element",
properties: {
opened: {
type: Boolean,
value: false
},
fach: {
type: String,
value: "u-oh an Error"
},
content: {
type: String,
value: "u-oh an Error"
}
},
toggleCollapse: function() {
if(this.opened) {
this.$.collapse.hide();
this.$.card.elevation = "2";
this.opened = false;
}
else {
this.$.collapse.show();
this.$.card.elevation = "5";
this.opened = true;
}
},
ready: function() {
var date = new Date(this.datum);
this.convertedDate = date.getDate() + "." + (date.getMonth() + 1) + "." + date.getFullYear();
}
});
</script>
</dom-module>
Polymer not allowed html to prevent XSS attack
But you can do this
<dom-module id="html-echo">
<style>
:host {
display: block;
}
</style>
<template>
</template>
</dom-module>
<script>
(function () {
Polymer({
is: 'html-echo',
properties: {
html: {
type: String,
observer: '_htmlChanged'
}
},
_htmlChanged: function (neo) {
// WARNING: potential XSS vulnerability if `html` comes from an untrusted source
this.innerHTML = neo;
}
});
})();
</script>
Use like
<html-echo html="[[htmlText]]"></html-echo>

Categories