how to open definite element of tree - javascript

can you help me with this, i dont know how to open element of tree by vue js.i mean open definite element. if future every element of tree will be wraped by rouer-link, but right now i dont know how to trigger mechanism to open element.
tree example here
enter link description here
or here
[enter link description here][2]
let tree = {
label: 'root',
nodes: [
{
label: 'item1',
nodes: [
{
label: 'item1.1'
},
{
label: 'item1.2',
nodes: [
{
label: 'item1.2.1'
}
]
}
]
},
{
label: 'item2'
}
]
}
Vue.component('tree-menu', {
template: '#tree-menu',
props: [ 'nodes', 'label', 'depth' ],
data() {
return {
showChildren: false
}
},
computed: {
iconClasses() {
return {
'fa-plus-square-o': !this.showChildren,
'fa-minus-square-o': this.showChildren
}
},
labelClasses() {
return { 'has-children': this.nodes }
},
indent() {
return { transform: `translate(${this.depth * 50}px)` }
}
},
methods: {
toggleChildren() {
this.showChildren = !this.showChildren;
}
}
});
new Vue({
el: '#app',
data: {
tree
}
})
body {
font-family: "Open Sans", sans-serif;
font-size: 18px;
font-weight: 300;
line-height: 1em;
}
.container {
width: 300px;
margin: 0 auto;
}
.tree-menu {
.label-wrapper {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #ccc;
.has-children {
cursor: pointer;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.3/vue.js"></script>
<div class="container">
<h4>Vue.js Expandable Tree Menu<br/><small>(Recursive Components)</small></h4>
<div id="app">
<tree-menu
:nodes="tree.nodes"
:depth="0"
:label="tree.label"
></tree-menu>
</div>
</div>
<script type="text/x-template" id="tree-menu">
<div class="tree-menu">
<div class="label-wrapper" #click="toggleChildren">
<div :style="indent" :class="labelClasses">
<i v-if="nodes" class="fa" :class="iconClasses"></i>
{{ label }}
</div>
</div>
<tree-menu
v-if="showChildren"
v-for="node in nodes"
:nodes="node.nodes"
:label="node.label"
:depth="depth + 1"
>
</tree-menu>
</div>
</script>

Related

Using onclick event, how to match name with multiple status by drawing lines in Vuejs?

new Vue({
el: "#app",
data: {
getQuestionAnswers: [
{
name: 'foo',
checked: false,
status: 'ok'
},
{
name: 'bar',
checked: false,
status: 'notok'
},
{
name: 'baz',
checked: false,
status: 'medium'
},
{
name: 'oo',
checked: false,
status: 'medium'
}
]
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
width:100%
}
.red {
color: red;
}
.bcom {
width: 100%;
display: flex;
}
.container1 {
width: 50px;
}
.container2 {
width: calc(100% - 105px);
padding: 8px 0;
height: 30px;
box-sizing: border-box;
}
.h-line {
height: 1px;
margin-bottom: 18px;
width: 100%;
background-color: black;
}
.container3{
margin-left: 5px;
width: 50px;
}
.point:hover {
width: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<div class="bcom"
v-for="(group, index) in getQuestionAnswers"
:key="index + group.name"
:group="group"
>
<div>
<input type="checkbox" v-model="group.checked"/>
{{ group.name }}
</div>
<div class="container2">
<div class="h-line" v-if="group.checked"></div>
</div>
<div>
<input type="checkbox"/>
{{ group.status }}
</div>
</div>
</div>
Onclick of checkbox, how to add multiple lines from one point in Vuejs?
As seen in the image, On click of the checkbox, Based on the status, I need to match from one point to three multiple status. like "ok, notok, medium"
i have taken v-model in the checkbox,to check and perfome two way data binding But not sure....what to do further. Do I need to take computed property and write condition to check and draw three multiple lines???
there are som positioning issues here, but this sample should be enough for you to get it working:
template
<div id="demo" :ref="'plane'">
<canvas :ref="'canvas'"></canvas>
<div
class="bcom"
v-for="(group, index) in getQuestionAnswers"
:key="index + group.name"
:group="group"
>
<div>
<input
type="checkbox"
v-on:click="() => onToggleCheckbox(group)"
v-model="group.checked"
:ref="'checkbox_' + group.name"
/>
<span>{{ group.name }}</span>
</div>
<div>
<span>{{ group.status }}</span>
<input type="checkbox" :ref="'status_' + group.name" />
</div>
</div>
</div>
script:
export default {
name: 'App',
data: () => ({
ctx: undefined,
draw(begin, end, stroke = 'black', width = 1) {
if (!this.ctx) {
const canvas = this.$refs['canvas'];
if (!canvas?.getContext) return;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
this.ctx = canvas.getContext('2d');
}
if (stroke) {
this.ctx.strokeStyle = stroke;
}
if (width) {
this.ctx.lineWidth = width;
}
this.ctx.beginPath();
this.ctx.moveTo(...begin);
this.ctx.lineTo(...end);
this.ctx.stroke();
},
onToggleCheckbox(group) {
const planeEl = this.$refs['plane'];
const planeRect = planeEl.getBoundingClientRect();
const fromEl = this.$refs['checkbox_' + group.name];
const fromRect = fromEl.getBoundingClientRect();
const from = {
x: fromRect.right - planeRect.left,
y: fromRect.top + fromRect.height / 2 - planeRect.top,
};
const toEl = this.$refs['status_' + group.name];
const toRect = toEl.getBoundingClientRect();
const to = {
x: toRect.left - planeRect.left,
y: toRect.top + toRect.height / 2 - planeRect.top,
};
console.log(planeRect, from, to);
this.draw(
Object.values(from),
Object.values(to),
group.checked ? 'white' : 'black',
group.checked ? 3 : 2
);
},
getQuestionAnswers: [
{
name: 'foo',
checked: false,
status: 'ok',
},
{
name: 'bar',
checked: false,
status: 'notok',
},
{
name: 'baz',
checked: false,
status: 'medium',
},
{
name: 'oo',
checked: false,
status: 'medium',
},
],
}),
};
style
body {
background: #20262e;
padding: 20px;
font-family: Helvetica;
}
#demo {
position: relative;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
canvas {
position: absolute;
background: red;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: #fff;
z-index: -1;
}
.bcom {
width: 100%;
display: flex;
justify-content: space-between;
z-index: 2;
}
this only draws one line but you could easily add the others. I figured you might change your data schema to something like:
getQuestions() {
{
name: string,
checked: boolean,
statuses: [string...],
},
getStatuses() {
{
name: string
}
but not knowing about your requirements here, I decided to post the above before making further changes. (here is the sort of refactor I was referring to: https://stackblitz.com/edit/vue-yuvsxa )
addressing first comment:
in app.vue only there is one data called[((questions))], inside question we are looping and setting the status.
this is easy to address with a bit of preprocessing:
questionsAndStatusesMixed: // such as [{...question, ...statuses}],
questions: [],
statuses: [],
mounted() {
const statusesSet = new Set()
this.questionsAndStatusesMixed.forEach(item => {
const question = {
name: item.name,
checked: item.checked,
answer: item.status // is this the answer or .. these never made sense to me,
statuses: this.statuses // assuming each question should admit all statuses/that is, draw a line to each
}
const status = {
name: item.name
}
this.questions.push(question)
statusesSet.add(status)
})
Array.from(statusesSet).forEach(item => this.statuses.push(item))
}

`How apply multiple event on single button?`

How apply multiple event on single button in Vue.js?
I have a single button component
When a button is clicked in parent, several events are
must be applied
tytle should change from "Buy" to "In a basket"
icon shold apply done
style should change to button_1
my button component
<template>
<div class="btn"
#click="click"
:class="className">
<i class="material-icons"> {{ icon }} </i>
<span> {{ title }} </span>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: 'Buy'
},
disabled: {
type: Boolean,
default: false
},
button_1: {
type: Boolean,
default: false
},
icon: {
type: String,
default: ''
},
},
data() {
return {}
},
computed: {
className() {
return {
'btn__disabled': this.disabled,
'btn__button_1': this.button_1,
}
}
},
methods: {
click() {
this.$emit('click')
}
},
name: "BaseButton"
}
</script>
<style lang="scss" scoped>
.material-icons {
font-size: 16px;
}
.btn {
position: relative;
font-family: 'Merriweather', sans-serif;
color: var(--color-primary-light);
left: 45%;
bottom: 18%;
height: 48px;
width: 122px;
cursor: pointer;
background-color: var(--color-grey-light-4);
display: flex;
justify-content: space-evenly;
align-items: center;
&:hover,
&:active {
background-color: var(--color-grey-light-2);
border: none;
}
&__button_1 {
color: var(--color-primary-light);
background-color: var(--color-grey-light-3);
border: none;
}
&__disabled {
background-color: var(--color-grey-light-1);
border: none;
pointer-events: none;
}
}
</style>
my parent component
<template>
<base-button #click="clickBtn"></base-button>
</template>
<script>
import BaseButton from '../components/ui/BaseButton'
export default {
name: "GalleryOverview",
components: {BaseButton},
methods: {
clickBtn() {
console.log('BTN clicked')
}
}
}
}
</script>
How can I apply multiple event on single button?
You are almost done, as you are sending emit to parent component, you can use that to change.
So, first you will need to pass the required props to the child component, as:
<template>
<base-button #click="clickBtn" :title="title" :icon="icon" :button_1="button_1"></base-button>
</template>
<script>
import BaseButton from '../components/ui/BaseButton'
export default {
name: "GalleryOverview",
data() {
return {
title: 'My Title',
icon: '',
button_1: false
}
}
methods: {
// This is where you can change.
clickBtn() {
this.icon = 'change icon';
this.title = 'change title';
this.button_1 = true;
}
}
}
</script>
Now when you click the button it will change the title, icon and button_1.

How to add class from content of a variable in Vue.js

I want to pass a variable to a component which should be added as a class to a div. However, Vue adds the name of the variable instead of the content.
So I pass the prop color which contains red.
What I want: <div class="red">2</div>
What I get: <div class="color">2</div>
I think this is a noob question, so sorry for that. Maybe there is a better way to do this.
Thanks for helping me out.
Here are my components:
<template>
<div class="btn btn-outline-primary cell"
:class="{color}"
:id="id">
{{ number }}
</div>
</template>
<script>
export default {
name: "TileElement",
props: ["id", "number", "color"]
}
</script>
<style scoped>
.green {
color: green;
}
.red {
color: red;
}
.yellow {
color: yellow;
}
.cell {
display: inline-block;
float: left;
margin: 0.1em;
text-align: center;
background-color: lightgray;
width: 2.7em;
height: 2.7em;
}
</style>
Parent Component:
<template>
<div class="row">
<TileElement
v-for="tile in tiles"
v-bind:key="tile.id"
v-bind:number="tile.number"
v-bind:color="tile.color"
></TileElement>
</div>
</template>
<script>
import TileElement from './TileElement.vue';
export default {
name: "TileRow",
components: {
TileElement
},
data: function () {
return {
tiles: [
{id: 1, number: 1, color: "green"},
{id: 2, number: 2, color: "red"},
{id: 3, number: 3, color: "yellos"}
]
}
}
}
</script>
If you just need to pass a class, without any conditions or other such stuff, then you can simple use array for one and any other number of classes:
<div :class="[color]"></div>
But that's not only you can do.
https://v2.vuejs.org/v2/guide/class-and-style.html
:class="color" will also work:
var vm = new Vue({
el: '#app',
data() {
return {
color: 'red'
};
}
});
.cell { width: 50px; height: 50px; }
.red { background: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>
<div id="app">
<div class="cell" :class="color"></div>
</div>
Try dynamically importing the class name
:class="{[color]: true}"

AngularJS Filter: Checkbox active by default based on attribute value

I am working on a prototype that uses AngularJS to filter JSON data. A working sandbox is here:
https://codepen.io/ixdarchitects/pen/BaypxrW
I need your help to solve 2 Problems:
How to use the "Check All" and "Uncheck All" button to activate/deactivate all of the checkbox filters?
Filter by default: How to make the webpage only show gray bird when the page is initialized?
Thank you
Image
HTML:
<div ng-app="petSelector" ng-controller="PetCtrl" class="wrapper">
<h1>Pet Picker!</h1>
<hr>
<h3>Problems to solve:</h3>
<ol>
<li>How to use the "Check All" and "Uncheck All" button to activate/deactivate all of the checkbox filters?</li>
<li>Filter by default: How to make the webpage only show gray bird when the page is initialized?</li>
</ol>
<hr>
<div class="attr" ng-repeat="(prop, ignoredValue) in pets[0].FilterAttributes" ng-init="filter[prop]={}" ng-class="prop">
<b>{{prop}}:</b><br />
<span class="checkbox" ng-repeat="opt in getOptionsFor(prop)">
<label><input type="checkbox" ng-model="filter[prop][opt]" /> {{opt}}</label>
</span>
</div>
<button ng-click="checkAll()" style="margin-right: 10px">Check all</button>
<button ng-click="uncheckAll()" style="margin-right: 10px">Uncheck all</button>
<div class="results">Number of results: {{filtered.length}}</div>
<div class="pet" ng-repeat="p in filtered=(pets | filter:filterByProp | orderBy:order)">
<img ng-src="{{p.img}}">
<p>{{p.name}}</p>
</div>
<div ng-if="filtered.length == 0">Sorry, nothing matches your selection</div>
</div>
JS:
var petSelector = angular.module("petSelector", []);
petSelector.controller("PetCtrl", [
"$scope",
function($scope) {
$scope.pets = [
{
name: "Finch",
FilterAttributes: { species: "bird", size: "x-small", color: "red" },
img:
"http://upload.wikimedia.org/wikipedia/commons/7/7c/Fringilla_coelebs_chaffinch_male_edit2.jpg"
},
{
name: "Cockatiel",
FilterAttributes: { species: "bird", size: "small", color: "yellow" },
img: "http://upload.wikimedia.org/wikipedia/commons/0/07/Captive.jpg"
},
{
name: "African Gray Parrot",
FilterAttributes: { species: "bird", size: "large", color: "gray" },
img:
"http://upload.wikimedia.org/wikipedia/commons/2/28/Psittacus_erithacus_-perching_on_tray-8d.jpg"
},
{
name: "Macaw",
FilterAttributes: { species: "bird", size: "x-large", color: "blue" },
img:
"http://upload.wikimedia.org/wikipedia/commons/0/00/Macaw.blueyellow.arp.750pix.jpg"
},
{
name: "Shih Tzu",
FilterAttributes: { species: "dog", size: "x-small", color: "multi" },
img: "http://upload.wikimedia.org/wikipedia/commons/3/30/Shih-Tzu.JPG"
},
{
name: "Border Collie",
FilterAttributes: { species: "dog", size: "small", color: "multi" },
img:
"http://upload.wikimedia.org/wikipedia/commons/b/b1/Border_Collie_liver_portrait.jpg"
},
{
name: "American Staffordshire Terrier",
FilterAttributes: { species: "dog", size: "large", color: "gray" },
img: "http://upload.wikimedia.org/wikipedia/commons/d/de/AmStaff2.jpg"
},
{
name: "Bullmastiff",
FilterAttributes: { species: "dog", size: "x-large", color: "brown" },
img:
"http://upload.wikimedia.org/wikipedia/commons/9/9e/Bullmastiff_Junghund_1_Jahr.jpg"
}
];
$scope.filter = {};
$scope.getOptionsFor = function(propName) {
return ($scope.pets || [])
.map(function(p) {
return p.FilterAttributes[propName];
})
.filter(function(p, idx, arr) {
return arr.indexOf(p) === idx;
});
};
$scope.filterByProp = function(pets) {
var matchesAND = true;
for (var prop in $scope.filter) {
if (noSubFilter($scope.filter[prop])) continue;
if (!$scope.filter[prop][pets.FilterAttributes[prop]]) {
matchesAND = false;
break;
}
}
return matchesAND;
};
function noSubFilter(subFilterObj) {
for (var key in subFilterObj) {
if (subFilterObj[key]) return false;
}
return true;
}
}
]);
CSS
* {
box-sizing: border-box;
}
body {
font-family: 'Helvetica', arial, sans-sarif;
color: #fff;
}
h1 {
color: #fff;
margin: 0;
}
p {
margin-top: 0;
}
b {
color: #fff;
text-transform: uppercase;
}
.wrapper {
width: 800px;
margin: 20px auto;
padding: 40px;
background: #00a5bb;
border-radius: 8px;
}
.attr {
width: 32%;
margin: 0 .5%;
padding: 20px;
display: inline-block;
vertical-align: top;
}
.checkbox {
width: 49%;
display: inline-block;
margin: 10px 0 0;
}
.results {
font-size: 12px;
margin: 10px 0 20px;
padding-bottom: 10px;
border-bottom: 1px solid white;
}
.pet {
margin-bottom: 10px;
display: inline-block;
width: 33%;
text-align: center;
}
.pet img {
max-width: 85%;
max-height: 200px;
}
.pet.ng-enter, .pet.ng-leave {
-webkit-transition: all linear 0.5s;
transition: all linear 0.5s;
}
.pet .ng-enter {
opacity: 0;
}
.pet.ng-enter-active {
opacity: 1;
height: auto;
}
.pet.ng-leave-active {
opacity: 0;
height: 0;
}
I achieve what you are asking for adding the following two $scope functions.
$scope.checkAll iterates all pets FilteredAttributes and their values and set them at true into $scopeFilter.
$scope.uncheckAll simply reset the $scopeFilter object.
For the default filter, I removed ng-init="filter[prop]={}" to initiliaze $scopeFilter in the .js file as follows :
$scope.filter = {species : {bird : true} , color : {gray: true}};
$scope.checkAll = function(){
const result = {};
$scope.pets.map(pet => pet.FilterAttributes)
.forEach( attribute => Object.keys(attribute)
.forEach( prop => {
if(result[prop]){
result[prop][attribute[prop]] = true
}
else
{
result[prop] = {};
result[prop][attribute[prop]] = true
}
})
);
$scope.filter = result;
};
$scope.uncheckAll = function(){
$scope.filter = {}
};
You can find the solution here https://codepen.io/dmnized/pen/povRQOE?editors=1010

Reactive object in 2 arrays

I have an array of objects (array 1), that can be toggled to another array (array 2). When added the user has the option to type in a text field for each option. The toggling works fine and is reactive on the initial creation. But if I have data that already exists in array 2, the item is no longer reactive.
I have made a quick jsfiddle to demonstrate: Event 1 and 3 are reactive, but event 2 no longer is as it already exists in the newEvents array. Is there anyway to get this connected to the original event?
new Vue({
el: "#app",
data: {
events: [
{ id: 1, text: "Event 1"},
{ id: 2, text: "Event 2"},
{ id: 3, text: "Event 3"}
],
savedEvents: [
{ id: 2, text: "Event 2", notes: 'Event Notes'}
]
},
methods: {
toggleEvent: function(event){
let index = this.savedEvents.findIndex(e => e.id == event.id);
if (index != -1) {
this.savedEvents.splice(index, 1);
} else {
this.savedEvents.push(event);
}
},
inArray: function(id) {
return this.savedEvents.some(obj => obj.id == id);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 5px;
border: 1px solid #666;
border-radius: 3px;
margin-bottom: 5px;
cursor: pointer;
}
input[type=text]{
padding: 5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Events:</h2>
<ol>
<li v-for="event in events">
<span class="btn" #click="toggleEvent(event)">
{{ event.text }}
</span>
<input type="text" placeholder="Type your note here..." v-model="event.notes" v-if="inArray(event.id)">
</li>
</ol>
<h2>
Saved Events:
</h2>
<ul>
<li v-for="event in savedEvents">
<strong>{{ event.text }}</strong> {{ event.notes }}
</li>
</ul>
</div>
The problem here is nothing to do with reactivity.
When you add an event to newEvents by clicking the button it's using the same object that's in events. As there's only one object for each event everything work fine.
In the case of Event 2 you're starting with two separate objects representing the same event, one in events and the other in newEvents. Changes to one will not change the other.
It's difficult to say what the appropriate solution is here without knowing your motivation for choosing these data structures but the example below ensures that both arrays contain the same object for Event 2.
The only thing I've changed from your original code is the data function.
new Vue({
el: "#app",
data () {
const data = {
events: [
{ id: 1, text: "Event 1"},
{ id: 2, text: "Event 2", notes: 'Event Notes'},
{ id: 3, text: "Event 3"}
],
newEvents: []
}
data.newEvents.push(data.events[1])
return data
},
methods: {
toggleEvent: function(event){
let index = this.newEvents.findIndex(e => e.id == event.id);
if (index != -1) {
this.newEvents.splice(index, 1);
} else {
this.newEvents.push(event);
}
},
inArray: function(id) {
return this.newEvents.some(obj => obj.id == id);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 5px;
border: 1px solid #666;
border-radius: 3px;
margin-bottom: 5px;
cursor: pointer;
}
input[type=text]{
padding: 5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Events:</h2>
<ol>
<li v-for="event in events">
<span class="btn" #click="toggleEvent(event)">
{{ event.text }}
</span>
<input type="text" placeholder="Type your note here..." v-model="event.notes" v-if="inArray(event.id)">
</li>
</ol>
<h2>
New Events:
</h2>
<ul>
<li v-for="event in newEvents">
<strong>{{ event.text }}</strong> {{ event.notes }}
</li>
</ul>
</div>
There are various ways you could represent this data other than by using two lists of the same objects. You might use a boolean flag within the objects. Or you could use a separate object to hold the notes, keyed by event id. It's difficult to know what would work best for your scenario.
Update:
Based on the comments, you could do something like this to use the objects in events as canonical versions when loading savedEvents:
loadSavedEvents () {
// Grab events from the server
someServerCall().then(savedEvents => {
// Build a map so that the objects can be grabbed by id
const eventMap = {}
for (const event of this.events) {
eventMap[event.id] = event
}
// Build the list of server events using the objects in events
this.savedEvents = savedEvents.map(savedEvent => {
const event = eventMap[savedEvent.id]
this.$set(event, 'notes', savedEvent.notes)
return event
})
})
}
As pointed out by #skirtle the object from the list array needs to be pushed into the second array for it to be reactive. I have solved this by looping through and matching the id and then pushing this object into the second array. Not sure if this is the best / most efficient way to do this but it works now.
new Vue({
el: "#app",
data: {
eventsList: [
{ id: 1, text: "Event 1"},
{ id: 2, text: "Event 2"},
{ id: 3, text: "Event 3"}
],
savedEvents: [
{ id: 2, text: "Event 2", notes: 'Event Notes'}
]
},
mounted() {
this.init();
},
methods: {
init: function() {
let _temp = this.savedEvents;
this.savedEvents = [];
_temp.forEach(event => {
this.eventsList.forEach(x => {
if (event.id == x.id) {
this.$set(x, "notes", event.notes);
this.savedEvents.push(x);
}
});
});
},
toggleEvent: function(event){
let index = this.savedEvents.findIndex(e => e.id == event.id);
if (index != -1) {
this.savedEvents.splice(index, 1);
} else {
this.savedEvents.push(event);
}
},
inArray: function(id) {
return this.savedEvents.some(obj => obj.id == id);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 5px;
border: 1px solid #666;
border-radius: 3px;
margin-bottom: 5px;
cursor: pointer;
}
input[type=text] {
padding: 5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Events:</h2>
<ul>
<li v-for="event in eventsList">
<span class="btn" #click="toggleEvent(event)">
{{ event.text }}
</span>
<input type="text" placeholder="Type your note here..." v-model="event.notes" v-if="inArray(event.id)">
</li>
</ul>
<h2>
Saved Events:
</h2>
<ul>
<li v-for="event in savedEvents">
<strong>{{ event.text }}</strong> {{ event.notes }}
</li>
</ul>
</div>
Try using $set and $delete for avoiding reactivity lost
https://v2.vuejs.org/v2/api/?#Vue-set
https://v2.vuejs.org/v2/guide/reactivity.html

Categories

Resources