link137 link138 link139 link140 link141 link142 link143 link144 link145 link146 link147 link148 link149 link150 link151 link152 link153 link154 link155 link156 link157 link158 link159 link160 link161 link162 link163 link164 link165 link166 link167 link168 link169 link170 link171 link172 link173 link174 link175 link176 link177 link178 link179 link180 link181 link182 link183 link184 link185 link186 link187 link188 link189 link190 link191 link192 link193 link194 link195 link196 link197 link198 link199 link200 link201 link202 link203 link204 link205 link206 link207 link208 link209 link210 link211 link212 link213 link214 link215 link216 link217 link218 link219 link220 link221 link222 link223 link224 link225 link226 link227 link228 link229 link230 link231 link232 link233 link234 link235 link236 link237 link238 link239 link240 link241 link242 link243 link244 link245 link246 link247 link248 link249 link250 link251 link252 link253 link254 link255 link256 link257 link258 link259 link260 link261 link262 link263 link264 link265 link266 link267 link268 link269 link270 link271 link272 link273

[Vue.js] Vue.js parent <-> child updating value, routing view

I’m having issue regarding updating parent prop in child view. In my case Contestant is parent, EditContestant should be child. Contestant.vue.js should store (yeah, probably answer is right here - store as in Vuex) user info and EditContestant should only render edit view, allow for edit user info action and save it via own method or parent method. I’ve included routing so you should get what I’m talking about.

Structure is:

Contestant.vue
|-EditContestant.Vue

Contestant.vue:

<script>
export default {
data() {
return {
contestant: {
id: this.$route.params.id,
gender: ‘’,
firstname: ‘’,
lastname: ‘’,
},
}
},
methods: {
fetchContestant(id) {
//some api call here
vm.updatePropContestant(res.data);
// …
},
updatePropContestant(newData) {
if (!this.contestant || this.contestant.length === 0) {
this.contestant = {};
}
this.contestant.firstname = newData.firstname;
this.contestant.lastname = newData.lastname;
this.contestant.id = newData.id;
this.contestant.gender = newData.gender;
// this.$forceUpdate();
},
},
}
</script>
<template>
<div>
<router-view :contestant=”contestant” @interface=”contestant = $event”></router-view>
</div>
</template>

EditContestant.vue

<script>
export default {
data() {
console.log(‘data’);
return {
editContestant: {
id: ‘’,
‘firstname’: ‘’,
‘lastname’: ‘’,
‘gender’: 0
},
edit: false
}
},
props: [‘contestant’],
created: function () {
// tried also to fetchContestant if parent beforeCreate method with same result, so tried moving it here :(
this.$parent.fetchContestant(this.$route.params.id);
}
}
</script>

<template>
<div class=”col”>
<input id=”firstname” v-model=”this.$parent.contestant.firstname” type=”text” class=”form-control” placeholder=”First name”
<!– this doesn’t help either v-on:input=”updateParentValue($event.target.value)” –> >
</div>
</template>

app.js

require(‘./bootstrap’);
window.vue.js = require(‘vue’);
import router from ‘./router’;
new Vue({
el: “#app”,
router,
// render: h => h(app)
});

router/index.js

import contestantComponent from ‘../components/Contestant/Contestant’
import contestantEditComponent from ‘../components/Contestant/EditContestant’
Vue.use(Router)
export default new Router({
routes: [
{
path: ‘/contestant/:id’,
component: contestantComponent,
children: [
{

name: ‘Contestant edit’,
component: contestantEditComponent,
path: ‘/contestant/:id?/edit’,
},
{
name: ‘View contestant’,
component: ViewContestantComponent,
path: ‘’,
}
],
]
})

When I add something to the input I get an error:

found in

-–> <EditContestant> at resources/js/components/Contestant/EditContestant.vue
<Contestant> at resources/js/components/Contestant/Contestant.vue
<Root>
warn @ app.js:41366
logError @ app.js:42625
globalHandleError @ app.js:42620
handleError @ app.js:42580
invokeWithErrorHandling @ app.js:42603
invoker @ app.js:42916
original._wrapper @ app.js:48273

and

app.js:42629 TypeError: Cannot read property ‘$parent’ of null
at _c.on.input (app.js:37434)
at invokeWithErrorHandling (app.js:42595)
at HTMLInputElement.invoker (app.js:42916)
at HTMLInputElement.original._wrapper (app.js:48273)

Solution :

removing this from this.$props… in EditContestatn.vue.js file helped. Thank you for the help @CloudSohJunFu. If you wish to answer to my question I will gladly accept the answer and delete my own.

Solution 2:

You don’t need this. in template, just use $parent. Template is already in the this. scope.

The communication between parent and child should be using Props down events up, instead of directly call the function thru this.$parent.function(). You should $emit(‘callFunc’) then @callFunc=”function”.

[Vue.js] Cannot recieve Post data sent from Vue via axios to PHP

devs. when running a local apache server. There are static vue.js files and ‘print’ folder with some script. when trying to send an http request from vue.js (via axios) to ‘print’ folder.

there is tried to use vue-resourse to send data, but I had the same problem.

Here is a vue.js method:

postData: function() {
const data = {
firstName: “John”,
lastName: “Doe”
};
const config = {
headers: {
“Content-Type”: “application/x-www-form-urlencoded”
}
};
axios
.post(“/print”, data, config)
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
}

The index.php file from print folder:

<?php
$postBody = file_get_contents(“php://input”);
$postBody = json_encode($postBody);
echo ‘Post: ‘,$postBody, ‘ here’;

Here are some screensots from network tab (sorry for quality)
when not sure why devtools treats request like GET, but I use POST

When I log the response into console it looks like that. Here the response is actually POST. But the data is still missing.

Prview tab looks like that.

Request actually reaches the file, but $postBody is simply an empty string. I guees the problem is that (“php://input”) does not get any input. When echo count($_POST) 0 is returned. Thanks for any help..

Solution :

There’s a couple of problems here which I’ll address in order.

You are sending JSON, not application/x-www-form-urlencoded so remove that Content-type request header. Axios defaults to application/json
Axios by default expects the response to be JSON but the PHP script is responding with plain text. Change the config to

const config = {
responseType: ‘text’
}

You are using json_encode() where you should be using json_decode(). The former turns a PHP data structure into a JSON-formatted string. The latter does the opposite.
On a hunch, if you’re using something like

<form @submit=”postData” action=”/print”>

then you need to change it to

<form @submit.prevent=”postData”>

to prevent the form from submitting normally. Same goes for if you’re using a form submit button with @click handler. That or use type=”button” so it won’t submit by default.

See https://vuejs.org/v2/guide/events.html#Event-Modifiers
the web server may be performing a redirect from /print to /print/index.php, transforming the POST request to GET. To be sure this doesn’t happen, use the full path in the URL.
Assuming everything works in the PHP, $postBody will be an instance of stdclass, the result of json_decode(). Attempting to echo that out won’t work very well. In fact, it will trigger an error like

Recoverable fatal error: Object of class stdClass could not be converted to string

but the error reporting level may not be set correctly for you to see. See How to get useful error messages in PHP?

If you’d just like to re-show the JSON, try

$postBody = json_decode(file_get_contents(‘php://input’)); // returns a stdclass
echo ‘Post: ‘, json_encode($postBody), ‘ here’;

Note that the response will not be valid JSON due to the “Post: “ and “ here” output.

[Vue.js] Vuejs vuetify link share via what's app, viber

Hi I created normal web app (Not a PWA) in vuetify. Most of times this web app is use in the mobile phones. So a button called “share on what’s app” what does this button should do is open the what’s app mobile app in the user’s phone and let them to share on a chat. Is this possible with the vuetify? I mean I need v-btn.

Solution :

You can use this -

<v-btn>
<a href=”whatsapp://send?text=The text to share!” data-action=”share/whatsapp/share”>Share via Whatsapp</a>
</v-btn>

All I did was look for the url tag that’s necessary for opening whatsapp from a web app and put it inside an a-href tag inside v-btn. I found help here.

Solution 2:

<v-btn>
<a href=”https://www.whatsapp.com/">Share via whatsapp</a>
</v-btn>

Use this to directly link to whatsapp website, and there it will ask you to open in app.
An easy hack.

[Vue.js] check login state, render an overlay if not logged in and continue if login succeeded

I use Vuejs with Vuetify and Vuex and want to create a simple app. Let’s say a very small todo app. For my backend I use an Express REST api and for the HTTP methods I use Axios.

To handle the session I read about two things:

When launching an Axios call I could get an error with the status code 401. I could deal with it using axios.interceptors.response.

instance.interceptors.response.use(res => res, (err) => {
if (err.response.status === 401) {
store.dispatch(‘authentication/destroySession’);
}

return err;
});

When redirecting to another route I could use the beforeRouteEnter event of the vue.js Router and check if the token is valid and not expired.

router.beforeEach((to, from, next) => {
const userIsLoggedIn = checkIfUserIsLoggedIn();

if (!userIsLoggedIn) {
next(false); // stay on this route
} else {
next(); // navigate to the next route
}
});

So far so good. But what happens if one of these approaches have to deal with a “not logged in” state? I don’t want to redirect the user to a login page because then he would loose his current work. And maybe he got no account so he needs to signup first.

If the route or REST endpoint is protected I would cancel the task to execute, show an error alert and after that I would like to render an overlay.

Most resources explain how to redirect to the login page if not logged in but Github for example renders the login page and executes the task after logging in.

How can I render this overlay? Is it even possible? Is there a better approach?

Solution :

Create the overlay HTML (can be in App.vue.js as you mentioned) whose visibility is dependent upon a computed called showOverlay:

<div v-show=”showOverlay”>OVERLAY CONTENT</div>

In the Vuex store, maintain some state which represents the visibility of the overlay:

state.showOverlay = false;

Back in App.vue, map this Vuex state into the showOverlay computed:

import { mapState } from ‘vuex’;
export default {
computed: {
…mapState([‘showOverlay’])
}
}

Wherever you use beforeRouteEnter, or in the router if using beforeEach, import the Vuex store directly (this makes it easy to access the store when this.$store is not accessible):

import store from ‘@/store.js’;

I see you posted example code which uses beforeEach instead of beforeRouteEnter, so use something like:

router.beforeEach((to, from, next) => {
const userIsLoggedIn = checkIfUserIsLoggedIn();

if (!userIsLoggedIn) {
store.state.showOverlay = true;
next(false); // stay on this route
} else {
next(); // navigate to the next route
}
});

After you get this working, it would be best to move the overlay into a component to avoid needlessly editing App.vue. And you’ll need to set the overlay’s state back to false on close.

[Vue.js] Parse Error Adjacent JSX elements must be wrapped in an enclosing tagThe problemSolutions

when trying to set up my React.js app so that it only renders if a variable there is set is true.

The way my render function is set up looks like:

render: function() {
var text = this.state.submitted ? ‘Thank you! Expect a follow up at ‘+email+’ soon!’ : ‘Enter the email to request early access:’;
var style = this.state.submitted ? {“backgroundColor”: “rgba(26, 188, 156, 0.4)”} : {};
return (
<div>

if(this.state.submitted==false)
{

<input type=”email” className=”input_field” onChange={this._updateInputValue} ref=”email” value={this.state.email} />

<ReactCSSTransitionGroup transitionName=”example” transitionAppear={true}>
<div className=”button-row”>
<a href=”#” className=”button” onClick={this.saveAndContinue}>Request Invite</a>
</div>
</ReactCSSTransitionGroup>
}
</div>
)
},

Basically, the important portion here is the if(this.state.submitted==false) portion (these divs to show up when the submitted variable is set to false).

But when running this, I get the error in the Question:

Uncaught Error: Parse Error: Line 38: Adjacent JSX elements must be wrapped in an enclosing tag

What is the issue here? And what can I use to make this work?

Solution :

You should put the component between an enclosing tag, Which means:

// WRONG!

return (
<Comp1 />
<Comp2 />
)

Instead:

// Correct

return (
<div>
<Comp1 />
<Comp2 />
</div>
)

Edit: Per Joe Clay’s comment about the Fragments API

// More Correct

return (
<React.Fragment>
<Comp1 />
<Comp2 />
</React.Fragment>
)

Solution 2:

It is late to answer this question but I thought It will add to the explanation.

It is happening because any where in the code you are returning two elements simultaneously.

e.g

return(
<div id=”div1”></div>
<div id=”div1”></div>
)

It should be wrapped in a parent element. e.g

return(
<div id=”parent”>
<div id=”div1”></div>
<div id=”div1”></div>
</div>
)

More Detailed Explanation

the below jsx code get transformed

class App extends React.Component {
render(){
return (
<div>
<h1>Welcome to React</h1>
</div>
);
}
}

into this

_createClass(App, [{
key: ‘render’,
value: function render() {
return React.createElement(
‘div’,
null,
React.createElement(
‘h1’,
null,
‘Welcome to React’
)
);
}
}]);

But if you do this

class App extends React.Component {
render(){
return (
<h1>Welcome to React</h1>
<div>Hi</div>
);
}
}

this gets converted into this(Just for illustration purpose, actually you will get error : Adjacent JSX elements must be wrapped in an enclosing tag)

_createClass(App, [{
key: ‘render’,
value: function render() {
return React.createElement(
‘div’,
null,
‘Hi’
);
return React.createElement(
‘h1’,
null,
‘Welcome to React’
)
}
}]);

In the above code you can see that you are trying to return twice from a method call, which is obviously wrong.

Edit- Latest changes in React 16 and own-wards:

If you do not want to add extra div to wrap around and want to return more than on child components you can go with React.Fragments.

React.Fragments are little bit faster and has less memory usage (no need to create an extra DOM node, less cluttered DOM tree).

e.g (In React 16.2.0)

render() {
return (
<>
React fragments.
<h2>A heading</h2>
More React fragments.
<h2>Another heading</h2>
Even more React fragments.
</>
);
}

or

render() {
return (
<React.Fragments>
React fragments.
<h2>A heading</h2>
More React fragments.
<h2>Another heading</h2>
Even more React fragments.
<React.Fragments/>
);
}

or

render() {
return [
“Some text.”,
<h2 key=”heading-1”>A heading</h2>,
“More text.”,
<h2 key=”heading-2”>Another heading</h2>,
“Even more text.”
];
}

Solution 3:

React element has to return only one element. You’ll have to wrap both of the tags with another element tag.

I can also see that the render function is not returning anything. This is how the component should look like:

var app = React.createClass({
render () {
/*React element can only return one element*/
return (
<div></div>
)
}
})

Also note that you can’t use if statements inside of a returned element:

render: function() {
var text = this.state.submitted ? ‘Thank you! Expect a follow up at ‘+email+’ soon!’ : ‘Enter the email to request early access:’;
var style = this.state.submitted ? {“backgroundColor”: “rgba(26, 188, 156, 0.4)”} : {};
if(this.state.submitted==false) {
return <YourJSX />
} else {
return <YourOtherJSX />
}
},

Solution 4:

If you don’t want to wrap it in another div as other answers have suggested, you can also wrap it in an array and it will work.

// Wrong!
return (
<Comp1 />
<Comp2 />
)

It can be written as:

// Correct!
return (
[<Comp1 />,
<Comp2 />]
)

Please note that the above will generate a warning: Warning: Each child in an array or iterator should have a unique “key” prop. Check the render method of ‘YourComponent’.

This can be fixed by adding a key attribute to the components, if manually adding these add it like:

return (
[<Comp1 key=”0” />,
<Comp2 key=”1” />]
)

Here is some more information on keys: http://facebook.github.io/react/docs/multiple-components.html#dynamic-children

Solution 5:

The problem

Parse Error: Adjacent JSX elements must be wrapped in an enclosing tag

This means that you are trying to return multiple sibling JSX elements in an incorrect manner. Remember that you are not writing HTML, but JSX! the code is transpiled from JSX into JavaScript. For example:

render() {
return (<p>foo bar</p>);
}

will be transpiled into:

render() {
return React.createElement(“p”, null, “foo bar”);
}

Unless you are new to programming in general, you already know that functions/methods (of any language) take any number of parameters but always only return one value. Given that, you can probably see that a problem arises when trying to return multiple sibling components based on how createElement() works; it only takes parameters for one element and returns that. Hence we cannot return multiple elements from one function call.

So if you’ve ever wondered why this works…

render() {
return (
<div>
<p>foo</p>
<p>bar</p>
<p>baz</p>
</div>
);
}

but not this…

render() {
return (
<p>foo</p>
<p>bar</p>
<p>baz</p>
);
}

it’s because in the first snippet, both <p>-elements are part of children of the <div>-element. When they are part of children then we can express an unlimited number of sibling elements. Take a look how this would transpile:

render() {
return React.createElement(
“div”,
null,
React.createElement(“p”, null, “foo”),
React.createElement(“p”, null, “bar”),
React.createElement(“p”, null, “baz”),
);
}

Solutions

Depending on which version of React you are running, you do have a few options to address this:

Use fragments (React v16.2+ only!)

As of React v16.2, React has support for Fragments which is a node-less component that returns its children directly.

Returning the children in an array (see below) has some drawbacks:

Children in an array must be separated by commas.
Children in an array must have a key to prevent Reacts key warning.
Strings must be wrapped in quotes.

These are eliminated from the use of fragments. Here’s an example of children wrapped in a fragment:

render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}

which de-sugars into:

render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}

Note that the first snippet requires Babel v7.0 or above.

Return an array (React v16.0+ only!)

As of React v16, React Components can return arrays. This is unlike earlier versions of React where you were forced to wrap all sibling components in a parent component.

In other words, you can now do:

render() {
return [<p key={0}>foo</p>, <p key={1}>bar</p>];
}

this transpiles into:

return [React.createElement(“p”, {key: 0}, “foo”), React.createElement(“p”, {key: 1}, “bar”)];

Note that the above returns an array. Arrays are valid React Elements since React version 16 and later. For earlier versions of React, arrays are not valid return objects!

Also note that the following is invalid (you must return an array):

render() {
return (<p>foo</p> <p>bar</p>);
}

Wrap the elements in a parent element

The other solution involves creating a parent component which wraps the sibling components in its children. This is by far the most common way to address this issue, and works in all versions of React.

render() {
return (
<div>
<h1>foo</h1>
<h2>bar</h2>
</div>
);
}

Note: Take a look again at the top of this answer for more details and how this transpiles.

Solution 6:

React 16.0.0 we can return multiple components from render as an array.

return ([
<Comp1 />,
<Comp2 />
]);

React 16.4.0 we can return multiple components from render in a Fragment tag. Fragment

return (
<React.Fragment>
<Comp1 />
<Comp2 />
</React.Fragment>);

Future React you wil be able to use this shorthand syntax. (many tools dont support it yet so you might want to explicitly write <Fragment> until the tooling catches up.)

return (
<>
<Comp1 />
<Comp2 />
</>)

Solution 7:

React 16 gets the return as an array so it should be wrapped by one element like div.

Wrong Approach

render(){
return(
<input type=”text” value=”” onChange={this.handleChange} />

<button className=”btn btn-primary” onClick= {()=>this.addTodo(this.state.value)}>Submit</button>

);
}

Right Approach (All elements in one div or other element you are using)

render(){
return(
<div>
<input type=”text” value=”” onChange={this.handleChange} />

<button className=”btn btn-primary” onClick={()=>this.addTodo(this.state.value)}>Submit</button>
</div>
);
}

Solution 8:

React components must wrapperd in single container,that may be any tag
e.g. “< div>.. < / div>”

You can check render method of ReactCSSTransitionGroup

Solution 9:

Import view and wrap in View. Wrapping in a div did not work for me.

import { View } from ‘react-native’;

render() {
return (
<View>
<h1>foo</h1>
<h2>bar</h2>
</View>
);
}

Solution 10:

Invalid: Not only child elements

render(){
return(
<h2>Responsive Form</h2>
<div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
<div className=”col-sm-4 offset-sm-4”>
<form id=”contact-form” onSubmit={this.handleSubmit.bind(this)} method=”POST”>
<div className=”form-group”>
<label for=”name”>Name</label>
<input type=”text” className=”form-control” id=”name” />
</div>
<div className=”form-group”>
<label for=”exampleInputEmail1”>Email address</label>
<input type=”email” className=”form-control” id=”email” aria-describedby=”emailHelp” />
</div>
<div className=”form-group”>
<label for=”message”>Message</label>
<textarea className=”form-control” rows=”5” id=”message”></textarea>
</div>
<button type=”submit” className=”btn btn-primary”>Submit</button>
</form>
</div>
)
}

Valid: Root element under child elements

render(){
return(
<div>
<h2>Responsive Form</h2>
<div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
<div className=”col-sm-4 offset-sm-4”>
<form id=”contact-form” onSubmit={this.handleSubmit.bind(this)} method=”POST”>
<div className=”form-group”>
<label for=”name”>Name</label>
<input type=”text” className=”form-control” id=”name” />
</div>
<div className=”form-group”>
<label for=”exampleInputEmail1”>Email address</label>
<input type=”email” className=”form-control” id=”email” aria-describedby=”emailHelp” />
</div>
<div className=”form-group”>
<label for=”message”>Message</label>
<textarea className=”form-control” rows=”5” id=”message”></textarea>
</div>
<button type=”submit” className=”btn btn-primary”>Submit</button>
</form>
</div>
</div>
)
}

Solution 11:

There is a rule in react that a JSX expression must have exactly one outermost element.

wrong

const para = (
<p></p>
<p></p>
);

correct

const para = (
<div>
<p></p>
<p></p>
</div>
);

[Vue.js] Copy a Kendo UI Vue Design

i consider myself a good developer but when it comes to design or struggle with bootstrap or css stuff i’m lost.
so i came here to ask for some help.

i’m using kendo ui with vue.
now i need to do a couple of cruds, and i was asked to copy the design of the following page.

well the thing is that i’m unable to copy that design… :(
not even the design, the controls don’t look like that at all.

can someone point me in the right direction?
i don’t even find that panel on kendo-vue.

thanks.
regards.

Solution :

First of all check the source of the page. You will be able to see the css classes that are being used. What is more you could spot the stylesheets being used and lookup the their sources.

Secondly, you don’t want to look for the whole panel on kendo-vue. Look for different components to assemble the panel: form, inputs, datepickers, selects etc.

Thirdly, you could view the whole theme on github . Just clone it and add the changes

Hope this helps

[Vue.js] How to draw shape from path in vue konva?

when trying to use konvajs inside vue. to draw an object from path data, but i don’t know how to do it. My main purpose is to get the path data from server, but first i would like to see some drawing in action.

Thank you!
All help appreciated.

<div>
<v-container>
<v-layout align-end justify-center row fill-height>
<v-flex xs12>
<v-stage :config=”configKonva”>
<v-layer>
<v-shape :config=”configShape”/>
</v-layer>
</v-stage>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
export default {
data() {
return {
configShape: {},
configKonva: {
width: 200,
height: 200
}
};
},
methods: {},
mounted() {
this.configShape = new Konva.Path({
fill: “#00D2FF”,
stroke: “black”,
strokeWidth: 4,
data: “m0,0L100,100L0,100L0,0”,
sceneFunc: function(context, shape) {
// special Konva.js method
context.fillStrokeShape(shape);
}
});
}
};
</script>```

Solution :

It is not recommended to use sceneFunc for built-in shapes (such as Konva.Path).

Take a look into shapes tutorial for vue-konva https://konvajs.org/docs/vue/Shapes.html.

If you want to create a Konva.Path you need to use v-path component:

<v-path
:config=”{
x: 200,
fill: ‘#00D2FF’,
stroke: ‘black’,
strokeWidth: 4,
data: ‘m0,0L100,100L0,100L0,0’,
}”
/>

Demo: https://codesandbox.io/s/32xxoon18p

You you want to have full control of drawing you can use custom shapes: https://konvajs.org/docs/vue/Custom\_Shape.html

Solution 2:

I could make it work. I don’t think, that this is the correct way, but now at least it’s working

mounted() {
this.configShape = new Konva.Path({
fill: “#00D2FF”,
stroke: “black”,
strokeWidth: 4,
data: “m0,0L100,100L0,100L0,0”,
sceneFunc: function(context, shape) {
let arr = shape.attrs.dataArray;

context.beginPath();
for (var i = 0; i < arr.length; i++) {
if (arr[i].command == “M”) {
context.moveTo(arr[i].points[0],arr[i].points[1]);
} else if (arr[i].command == “L”) {
context.lineTo(arr[i].points[0],arr[i].points[1]);
}
}
context.closePath();

// special Konva.js method
context.fillStrokeShape(shape);
}
});
}

[Vue.js] Vue Array.splice() doesn't remove DOM element in element-ui table

there is a table with a hierarchical structure. When I try to remove one of the children with “array.splice”, vue.js does not delete its Dom structure reactively. Has anyone come across this? What are the solutions?

Reproduced this problem by the example of the table c site Vuejs

var Main = {
data() {
return {
tableData: [{
id: 1,
date: ‘2016-05-02’,
name: ‘wangxiaohu’
}, {
id: 2,
date: ‘2016-05-04’,
name: ‘wangxiaohu’
}, {
id: 3,
date: ‘2016-05-01’,
name: ‘wangxiaohu’,
children: [{
id: 31,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}, {
id: 32,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}]
}, {
id: 4,
date: ‘2016-05-03’,
name: ‘wangxiaohu’
}],
tableData1: [{
id: 1,
date: ‘2016-05-02’,
name: ‘wangxiaohu’
}, {
id: 2,
date: ‘2016-05-04’,
name: ‘wangxiaohu’
}, {
id: 3,
date: ‘2016-05-01’,
name: ‘wangxiaohu’,
hasChildren: true
}, {
id: 4,
date: ‘2016-05-03’,
name: ‘wangxiaohu’
}]
}
},
methods: {
load(tree, treeNode, resolve) {
resolve([
{
id: 31,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}, {
id: 32,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}
])
},
removeRow(row){
this.tableData[2].children.splice(0,1);
//this.tableData.splice(0,1);
}
},
}
var Ctor = Vue.extend(Main)
new Ctor().$mount(‘#app’)
@import url(“//unpkg.com/element-ui@2.7.2/lib/theme-chalk/index.css”);
<script src=”//unpkg.com/vue/dist/vue.js”></script>
<script src=”//unpkg.com/element-ui@2.7.2/lib/index.js”></script>
<div id=”app”>
<template>
<div>
<el-button @click=”removeRow”>
Delete child
</el-button>
<el-table
:data=”tableData”
style=”width: 100%;margin-bottom: 20px;”
border
row-key=”id”>
<el-table-column
prop=”date”
label=””
sortable
width=”180”>
</el-table-column>
<el-table-column
prop=”name”
label=”name”
sortable
width=”180”>
</el-table-column>
</el-table>

<el-table
:data=”tableData1”
style=”width: 100%”
row-key=”id”
border
lazy
:load=”load”
\>
<el-table-column
prop=”date”
label=”date”
width=”180”>
</el-table-column>
<el-table-column
prop=”name”
label=”name”
width=”180”>
</el-table-column>
</el-table>
</div>
</template>
</div>

when using vue.js 2.6.10 and element-ui 2.7.0

Solution :

It seems to be an issue with the way element-ui handles data internally. When modifying nested data directly, the table is not getting re-rendered. (But the data was indeed mutated correctly, as could be seen when logging this.tableData after the splice().)

It helps to create a copy of the tableData (you might need a workaround/polyfill for Array.from() if you’d like to support older browsers), modify that and set tableData to the mutated copy.

(Open the snipped in fullscreen mode and either click the button twice, or expand the children before clicking the button, as the children are collapsed by default and after re-rendering.)

var Main = {
data() {
return {
tableData: [{
id: 1,
date: ‘2016-05-02’,
name: ‘wangxiaohu’
}, {
id: 2,
date: ‘2016-05-04’,
name: ‘wangxiaohu’
}, {
id: 3,
date: ‘2016-05-01’,
name: ‘wangxiaohu’,
children: [{
id: 31,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}, {
id: 32,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}]
}, {
id: 4,
date: ‘2016-05-03’,
name: ‘wangxiaohu’
}],
tableData1: [{
id: 1,
date: ‘2016-05-02’,
name: ‘wangxiaohu’
}, {
id: 2,
date: ‘2016-05-04’,
name: ‘wangxiaohu’
}, {
id: 3,
date: ‘2016-05-01’,
name: ‘wangxiaohu’,
hasChildren: true
}, {
id: 4,
date: ‘2016-05-03’,
name: ‘wangxiaohu’
}]
}
},
methods: {
load(tree, treeNode, resolve) {
resolve([
{
id: 31,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}, {
id: 32,
date: ‘2016-05-01’,
name: ‘wangxiaohu’
}
])
},
removeRow(row){
var newTableData = Array.from(this.tableData);
newTableData[2].children.splice(0,1)
this.tableData = newTableData;
//this.tableData.splice(0,1);
}
},
}
var Ctor = Vue.extend(Main)
new Ctor().$mount(‘#app’)
@import url(“//unpkg.com/element-ui@2.7.2/lib/theme-chalk/index.css”);
<script src=”//unpkg.com/vue/dist/vue.js”></script>
<script src=”//unpkg.com/element-ui@2.7.2/lib/index.js”></script>
<div id=”app”>
<template>
<div>
<el-button @click=”removeRow”>
Delete child
</el-button>
<el-table
:data=”tableData”
style=”width: 100%;margin-bottom: 20px;”
border
row-key=”id”>
<el-table-column
prop=”date”
label=””
sortable
width=”180”>
</el-table-column>
<el-table-column
prop=”name”
label=”name”
sortable
width=”180”>
</el-table-column>
</el-table>

<el-table
:data=”tableData1”
style=”width: 100%”
row-key=”id”
border
lazy
:load=”load”
\>
<el-table-column
prop=”date”
label=”date”
width=”180”>
</el-table-column>
<el-table-column
prop=”name”
label=”name”
width=”180”>
</el-table-column>
</el-table>
</div>
</template>
</div>

[Vue.js] vue data function syntax

I’m getting following syntax error when compilling my assets:

Syntax Error: SyntaxError: C:\xampp\htdocs\dtcburger.com\resources\js\components\stripe\STRIPEform3.vue: Unexpected token, expected “;” (51:12)

49 | {
50 | stripe:null,
\> 51 | stripePK: stripePK,
| ^
52 | stripeStyles: stripeStyles,
53 | cardNumberElement:null,
54 | cardExpiryElement:null,

Here is how my code looks, is it because I used ES syntax for component data?

Solution :

You should return an object inside the data function like :

data:()=>{
return {
stripe:null,
stripePK: stripePK

}
}

Solution 2:

You need to return the object - wrap the function in parentheses and simply return the object literal:

data: () => (
{
stripe: null,
stripePK: stripePK,
//All the other properties
}
)

Alternatively, use the return statement:

data: () => {
return {
stripe: null,
stripePK: stripePK
//All the other properties
}
}

Solution 3:

The main reason for the error is caused because {} is interpreted as a code block and not as an object literal. If you see carefully, there is no red squiggly underline on the first stripe:null, property. Because, it is interpreted as a labeled statement.

This doesn’t throw an error:

{
stripe: null
}

This throws an error saying Unexpected token :

{
stripe: null,
stripePK: “stripePK”
}

To fix the code, you need to either return from the function

data: () => {
return {
stripe: null,
stripePK: stripePK,

}
}

OR, implicitly return from the arrow function by wrapping the object literal in parentheses:

data: () => ({
stripe: null,
stripePK: stripePK,

})

[Vue.js] Generic components in vue

I’m making a quiz in Vue.js, quiz questions can be different types:

Select one
Select multiple
Select image
Match

My problem is that types of questions are mixed (e.g. you can have any of them in the quiz) and thus are different components (<x-select-one-question>, <x-select-multiple-question>, <x-select-image-question>, <x-match> etc) so I can’t simply put one component into quiz.

How can, and should I make a generic component for this? Maybe something like this?

<template>
<div>
<x-question
v-for=”(question, index) in questions”
:key=”index”
type=”question.type”></x-question>
</div>
</template>

Solution :

the component could be something like that

<template>
<select v-if=”type == ‘select’”>
<option v-for=”item in items” value=”item.value”>{ item.text }</option>
</select>
<select v-else-if=”type == ‘multiple’” multiple>
<option v-for=”item in items” value=”item.value”>{ item.text }</option>
</select>
<input v-else-if=”type == ‘image’” type=”file” id=”image” name=”image” accept=”image/png, image/jpeg”>
</template>

Vue.component(‘question’, {
template: ‘#question’,
props: {
type: {
default: ‘’
},
items: {
type: Array,
default: [
{ value: 1, text: ‘One’ },
{ value: 2, text: ‘Two’ },
{ value: 3, text: ‘Three’ }
]
}
}
});

With that, you should be able to pass the correct prop like ‘select’, ‘multiple’ or ‘image’ to show the input you want.

<div id=”app”>
<question type=’image’></question>
</div>

Here’s a fiddle if you want to try by yourself.