Vue-Validator form validation not working on JS Fiddle - javascript

I want to ask a question concerning vue-validator but it is not working on JSFiddle. Can someone please help me check what the issue is so that I can go ahead and ask the main question
See JSFiddle
Html:
<div id="app">
<validator name="instanceForm">
<form v-on:submit.prevent="addInstance()">
<div class="form-group">
<input id="'instancetext" type="text" class="form-control" placeholder="Enter new Instance" v-validate:instancetext="{ required: { rule: true, message: 'What is the instance ?'}}" v-model="todo.name">
<div class="errors" v-if="showErrors">
<span v-if="$instanceForm.instancetext.required">{{$instanceForm.instancetext.required}}</span>
</div>
</div>
<div class="form-group">
<button class="btn btn-default"> <i class="fa fa-plus"> </i> Add
</button>
</div>
</form>
</validator>
<div class="">
<div v-for="todo in todoStore" class="list-group">
<div class="list-group-item">
<h4>
Main Card
</h4> {{todo.name}} {{todo.id}}
</div>
<div class="list-group-item nopadding">
<button class="btn btn-xs btn-danger margin-10" v-on:click="todoDelete(todo)">
<i class=" fa fa-trash"></i>
</button>
<form #submit="addNoteInstance">
<div class="form-group">
<input id="note-#{{note.id}}" type="text" class="form-control" name="note-#{{note.id}}" placeholder="Enter new Note Instance" v-model="name">
<button type="submit"><i class="fa fa-plus"> Add Note Instance</i></button>
</div>
</form>
</div>
<div v-for="note in todoNoteStore" class="list-group nopadding nomargin">
<div v-if="todo.id == note.id">
<div class="list-group-item">
<h4>
Note fore card {{todo.id}}
</h4> {{note.id}}{{note.name}}
</div>
<div class="list-group-item nopadding">
<button class="btn btn-xs btn-danger margin-10" v-on:click="removeNoteInstance(note)">
<i class=" fa fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<pre>{{ $data | json }}</pre>
</div>
Js:
new Vue({
el: '#app',
data: function() {
return {
showErrors: false,
todo: {
id: 1,
name: '',
completed: false,
check: ''
},
todoNote: {
id: 1,
name: '',
completed: false,
check: ''
},
todoStore: [
],
todoNoteStore: [
]
}
},
methods: {
addInstance: function() {
if (this.$instanceForm.valid) {
this.todoStore.push(this.todo);
this.todo = {};
this.showErrors = false;
} else {
this.showErrors = true;
}
},
addNoteInstance: function(e) {
e.preventDefault();
this.todoNoteStore.push({
"id": 1,
"name": this.name,
"completed": false,
"check": ''
});
this.name = '';
},
removeNoteInstance: function(note) {
this.todoNoteStore.remove(note);
}
}
});
css:
.nopadding {
padding-top: 0px;
!important;
padding-bottom: 0px;
!important;
}
.nomargin {
margin: 0px;
}

There are two problems here.
The CDN you are using for Vue-Validator (v2.1.7) seems to be broken. The links for 2.1.6 and 3.0.0-alpha1 seem to be fine. (this is specifically referring to links on cdnjs)
Vue-Validator 2.x only works with Vue 1.x. Your CDN for Vue is pointing to Vue 2.0.3.
So, either use Vue 1.x and a a working version of Vue-Validator 2.x, or use Vue 2.x and Vue-Validator 3.x (which is currently in alpha).

Related

How do I bind a card to a button in Angular when there are multiple cards fetching data from database

I am making a blogpost app using Angular and REST service. I need to have an edit and delete functionality in the application and this is what I have done for it
Component Code :
export class EditblogsComponent implements OnInit {
allBlogs: any;
constructor(private http: HttpClient) {}
ngOnInit(): void {
this.http.get('http://localhost:3000/blogPosts').subscribe(
(data) => {
this.allBlogs = data as string[];
},
(err: HttpErrorResponse) => {
console.log(err.message);
}
);
}
editBlog() {}
deleteBlog() {}
}
HTML code
<div class="container">
<div class="row">
<div class="col-md-10">
<div class="card border-primary" *ngFor="let blog of allBlogs">
<div class="card-body">
<div class="card-title">
<h1>
{{blog.blogTitle}}
</h1>
</div>
<div class="card-text text-left">
{{blog.blogContent}}
</div>
</div>
<footer class="blockquote-footer">
<blockquote class="blockquote mb-0 text-end">
Written by : {{blog.blogUser}}
</blockquote>
</footer>
<div class="row button-row">
<div class="col-sm-2">
<button class="btn btn-primary" (click)="editBlog()">Edit
blog</button>
</div>
<div class="col-sm-2">
<button class="btn btn-primary" (click)="deleteBlog()">Delete
blog</button>
</div>
</div>
</div>
<br>
</div>
<br>
</div>
<br>
</div>
JSON Server for the blog section:
"blogPosts": [
{
"blogUser": "usera",
"blogTitle": "Title for first blogppost",
"blogContent": "Content of first blogpost",
"id": 1
},
{
"blogUser": "usera",
"blogTitle": "Title for second blogppost",
"blogContent": "Content of second blogpost",
"id": 2
}
],
I want to know how I can bind the edit and delete buttons so that they work on the specific blog that renders in the cards.
Provide the blog or it's id as an argument to the functions.
html
<div class="row button-row">
<div class="col-sm-2">
<button class="btn btn-primary" (click)="editBlog(blog)">Edit
blog</button>
</div>
<div class="col-sm-2">
<button class="btn btn-primary" (click)="deleteBlog(blog.id)">Delete
blog</button>
</div>
</div>
component
editBlog(blog: Blog) {}
deleteBlog(blogId: number) {}
Send the specific 'blog' object as an argument to the edit and delete methods like so:
HTML:
<div class="row button-row">
<div class="col-sm-2">
<button class="btn btn-primary" (click)="editBlog(blog)">Edit
blog</button>
</div>
<div class="col-sm-2">
<button class="btn btn-primary" (click)="deleteBlog(blog)">Delete
blog</button>
</div>
</div>
TS:
editBlog(blog:any)
{
}
deleteBlog(blog:any)
{
}

how can I make an v-if depending on a boolean object property?

I have a array of objects(comments from posts kind like facebook comments or any other social network) and I iterate it with an v-for, then I have on each comment a dropdown button with "edit" and "delete" buttons, I would like that when I press the edit button the comment would change to an input so I can edit it, so I added a property click_to_edit initialize in false to each comment object, so when I click on edit it changes the condition that the v-for is related to. But it does not change it, I guess it is that as the property is inside an object it always return false and therefore the condition never changes, but I do not know how else do this. This is the html for the v-for:
<div
class="mb-2"
v-bind:class="'comment_'+post.id"
v-for="(comment, index) in comments"
:key="index"
v-if="comment.id_post === post.id"
>
<div class="row">
<div class="col-img-user-post text-center">
<img
class="rounded-circle img-icon-profile"
:src="routes.user_files+'/'+comment.code+'/'+comment.picture"
alt
/>
</div>
<div class="col">
<div class="row">
<div class="col">
<div class="card-comment">
<div class="row">
<div v-if="!comment.clicked_to_edit" class="col">
<p class="mt-2 mb-2">{{ comment.description }}</p>
<p class="mb-0 font-smaller grey-color">{{ comment.time_ago }}</p>
</div>
<div v-if="comment.clicked_to_edit" class="col">
<input v-model="comment.description" type="text" />
<p class="mb-0 font-smaller grey-color">{{ comment.time_ago }}</p>
</div>
<div class="col-1">
<div class="row dropdown">
<div class="col">
<a
class="font-smaller"
type="button"
:id="'dropdownMenuButtonComment_'+index"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fas fa-lg fa-angle-down grey-color"></i>
</a>
<div
class="dropdown-menu dropdown-menu-right"
:aria-labelledby="'dropdownMenuButtonComment_'+index"
>
<button
class="dropdown-item"
v-if="comment.id_user===profile_info.id_user"
#click="editComment(comment.id, index)"
>
<i class="far fa-edit"></i>
Edit
</button>
<button
class="dropdown-item"
data-toggle="modal"
data-target="#modalDeleteComment"
v-if="comment.id_user===profile_info.id_user"
#click="actionComment(comment.id, 2, index)"
>
<i class="far fa-trash-alt red-color"></i>
<span class="red-color">Delete</span>
</button>
<button
class="dropdown-item"
v-if="comment.id_user!==profile_info.id_user"
#click="actionComment(comment.id, 3)"
>
<i class="far fa-flag"></i>
Report
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The object comment stated in the data:
comment: {
id: "",
id_post: "",
description: "",
clicked_to_edit: false,
id_user: this.profile_info.id_user,
code: this.profile_info.code,
name: this.profile_info.name,
surname_1: this.profile_info.surname_1,
surname_2: this.profile_info.surname_2,
nick: this.profile_info.nick,
picture: this.profile_info.picture,
role: this.profile_info.id_role,
time_ago: "0 minutes"
},
and the edit function:
editComment(id, index) {
this.comments[index].clicked_to_edit = true;
console.log(this.comments[index]);
},
I purposefully ignored your model, to show a general case. If you need help applying it to your case, let me know.
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data: () => ({
comments: [
{ id: 'one', description: "test 1" },
{ id: 'two', description: "test 2" },
{ id: 'three', description: "test 3" }
].map(i => ({ ...i,
isEditing: false
}))
}),
methods: {
async toggleEditing(comment, index) {
const isOpening = !comment.isEditing;
this.comments
.filter(c => c.isEditing)
.forEach(c => c.isEditing = false);
if (isOpening) {
comment.isEditing = true;
await this.$nextTick();
this.$refs.comments[index].querySelector('input').focus()
}
},
blur: ev => ev.target.blur()
}
})
.comment {
min-height: 21px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(comment, i) in comments" ref="comments" :key="comment.id">
<div v-if="!comment.isEditing"
v-text="comment.description"
class="comment"
#click="toggleEditing(comment, i)"></div>
<div v-else>
<input v-model="comment.description"
#blur="toggleEditing(comment)"
#keyup.enter="blur"
/>
</div>
</div>
</div>

Programmatic Navigation with vue-router produces a error

i creating a SPA with vue.js, in the form component want that when finish submit redirect to list component but happen that Uncaught (in promise) TypeError: Cannot read property 'data' of undefined.
I do not know why this error occurs if someone could correct my code, I would appreciate a clear explanation that I am doing wrong
<template>
<div class="row center-element">
<h1 class="pink-text center-align">{{title}}</h1>
<form class="col s12 m12 " #submit.prevent="save">
<div class="row ">
<div class="input-field col s12 m12">
<i class="material-icons prefix light-blue-text">pets</i>
<input id="name" type="text" class="validate" v-model="form.name">
<label for="name">name</label>
</div>
</div>
<div class="row">
<div class="file-field input-field col s12 m12">
<i class="material-icons prefix light-blue-text">image</i>
<input id='image' type="file">
<div class="file-path-wrapper ">
<input class="file-path validate" type="text">
</div>
</div>
</div>
<div class="row right-align">
<button class="btn-floating waves-effect waves-light light-blue " type="submit" name="action">
<i class="material-icons right">send</i>
</button>
<router-link to="/" class="btn-floating waves-effect waves-light light-blue ">
<i class="material-icons right">cancel</i>
</router-link>
</div>
</form>
</div>
</template>
<script>
export default {
data() {
return{
title:'Create',
store: '/admin/animals',
method: 'post',
form:{},
errors:'',
msm:''
}
},
beforeMount() {
if(this.$route.meta.mode === 'edit') {
this.title = 'Edit'
this.form.name = this.$route.params.name
this.store = 'animals/' + this.$route.params.id
this.method = 'post'
}
},
methods:{
save(){
let vm = this
let formData = new FormData();
formData.append('name',this.form.name)
formData.append('image',image.files[0])
if (this.title==='Edit') {
formData.append('_method', 'PATCH')
}
axios[this.method](this.store, formData).then(function(response) {
vm.$route.push('/list')
}).catch(function(error) {
Vue.set(vm.$data, 'errors', error.response.data)
})
},
}
}
</script>
I managed to solve the errors in the code,
there are several errors:
1.the line code vm.$route.push('/list'), generates an error for which the response.data property is not defined
2.the parameter that receive the function push() is the problem,i had to change '/list' for a variable redirect:'list'
<template>
<div class="row center-element">
<h1 class="pink-text center-align">{{title}}</h1>
<form class="col s12 m12 " #submit.prevent="save">
<div class="row ">
<div class="input-field col s12 m12">
<i class="material-icons prefix light-blue-text">pets</i>
<input id="name" type="text" class="validate" v-model="form.name">
<label for="name">name</label>
</div>
</div>
<div class="row">
<div class="file-field input-field col s12 m12">
<i class="material-icons prefix light-blue-text">image</i>
<input id='image' type="file">
<div class="file-path-wrapper ">
<input class="file-path validate" type="text">
</div>
</div>
</div>
<div class="row right-align">
<button class="btn-floating waves-effect waves-light light-blue " type="submit" name="action">
<i class="material-icons right">send</i>
</button>
<router-link to="/" class="btn-floating waves-effect waves-light light-blue ">
<i class="material-icons right">cancel</i>
</router-link>
</div>
</form>
</div>
</template>
<script>
export default {
data() {
return{
title:'Create',
store: '/admin/animals',
method: 'post',
form:{},
errors:'',
msm:'',
redirect:'/'
}
},
beforeMount() {
if(this.$route.meta.mode === 'edit') {
this.title = 'Edit'
this.form.name = this.$route.params.name
this.store = 'animals/' + this.$route.params.id
this.method = 'post'
}
},
methods:{
save(){
let vm = this
let formData = new FormData();
formData.append('name',this.form.name)
formData.append('image',image.files[0])
if (this.title==='Edit') {
formData.append('_method', 'PATCH')
}
axios[this.method](this.store, formData).then(function(response) {
Vue.set(vm.$data,'msm',response.data)
vm.$router.push(vm.redirect)
}).catch(function(error) {
Vue.set(vm.$data, 'errors', error)
})
},
}
}
</script>

Nested ng-repeat and push object

I have written an API which consumes this JSON
{
"savedBy": "1",
"symptom": "new",
"questionSet": [{
"question": "This is question 1",
"options": [{
"values": "okasdsad"
},
{
"values": "asdsad",
"subQuestionSet": [{
"question": "This is question 1",
"options": [{
"values": "okasdsad"
},
{
"values": "oaskdosakdo"
},
{
"values": "yoyoyo"
},
{
"values": "nonono"
}
]
}]
},
{
"values": "yoyoyo"
},
{
"values": "nonono"
}
]
}]
}
Now I have written the front-end in angular so that I can send this JSON value by the form,
HTML.
<div class="question" ng-repeat="qItem in questionVo track by $index">
{{questionVo}}
<div class="col-md-12">QUS {{$index+1}}
<input type="text" ng-model="qItem.question" class="form-control" id=""></div>
{{question}}
<div class="form-inline col-md-10 col-md-offset-2">
<div class="form-group" ng-repeat="items in optionsVo track by $index">
{{optionsVo}}
<label>{{$index+1}}</label><input ng-model="items.values" type="text" class="form-control" id="">
<i class="fa fa-plus-square" ng-click="addoptionsVo(items)"></i>
<i class="fa fa-minus-square" ng-click="optionsVo.splice($index, 1)"></i>
<button class="btn btn-primary" ng-click="showSubset()">Add Subset</button>
<!--------subset ----->
<div class="question" ng-if="showSubsetView == true" ng-repeat="SubqItem in ssss track by $index">
<div class="col-md-12">QUS {{$index+1}}
<input type="text" ng-model="question" class="form-control" id=""></div>
<div class="form-inline col-md-10 col-md-offset-2">
{{itemsz.ssss}}
<div class="form-group" data-ng-repeat="Subitems in optionsVo track by $index">
<label>{{$index+1}}</label><input type="text" class="form-control" id="">
<i class="fa fa-plus-square" ng-click="addoptionsVo($index)"></i>
<i class="fa fa-minus-square" ng-click="optionsVo.splice($index, 1)"></i>
<button class="btn btn-primary">Add Subset</button>
</div>
<div class="clearfix"></div>
<div class="btn-margin"><button class="btn btn-primary">Add More</button></div>
</div>
<div class="clearfix"></div>
</div>
<!--------subset ----->
</div>
<div class="clearfix"></div>
<div class="btn-margin"><button class="btn btn-primary">Add More</button></div>
</div>
<div class="clearfix"></div>
</div>
Angular JS
$scope.questionVo = [{
question: '',
}];
$scope.addquestionVo = function($event) {
$scope.questionVo.push({
question: '',
});
};
$scope.optionsVo = [{}];
$scope.addoptionsVo = function($event) {
$scope.optionsVo.push({});
};
PROBLEM
1.)when i add second question in the array the options remain same like in the 1st question
2.) i want to make json same as the api json in the question through angular
also
"options": [{
"values": "okasdsad"
},
"subQuestionSet": [{
"question": "This is question 1",
"options": [{
"values": "okasdsad"
},
{
"values": "oaskdosakdo"
},
{
"values": "yoyoyo"
},
{
"values": "nonono"
}
]
}] {
"values": "okasdsad"
}
]
can anyone help me with this?
anyone>?
PLUNKER https://plnkr.co/edit/33mVEQ?p=preview
EDIT : i found strange issue with plunker / in chrome it is giving {[ "values": "asdsa"]] but in plunker it is becoming [{ "values": "asdsa" }]
Find the below approach that matches your requirement. The options should be inside the question array.
'use strict';
var app = angular.module('medparser',[]);
app.controller('addquestionController', function($scope, $http, $window, $rootScope, $timeout) {
$scope.addoptionsVo = function(no) {
$scope.questionVo[no].options.push({
values: ''
});
};
$scope.questionVo = [{
question: '',
options: [{
"values": ""
}]
}];
$scope.addquestionVo = function($event) {
console.log("ASDSA");
$scope.questionVo.push({
question: '',
options: [{
"values": ""
}]
});
};
//////////////////////////////////////////////
$scope.showSubsetView = false;
$scope.showSubset = function() {
$scope.showSubsetView = true;
};
});
////////////////////////////////////////
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="medparser" ng-controller="addquestionController">
<div class="intro-header">
<div style="height:1px"></div>
<nav class="navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="index1.html">
<div class="logo">
<img src="images/logo.png"></div>
</a>
</div>
<div class="header-text">
Questionnaire For Doctors
</div>
</div>
</nav>
</div>
<div class="container header-padding">
<div class="col-md-6">Symptoms</div><br>
<div class="col-md-6"><input type="text" ng-model="keyword" class="form-control" ng-keyup="searchsymptoms(keyword)" typeahead="state.name for state in symptomsList | filter:$viewValue | limitTo:8" id=""></div>
<div class="clearfix"></div>
question : {{questionVo}}
<div class="question" ng-repeat="qItem in questionVo track by $index">
<div class="col-md-12">QUS {{$index+1}}
<input type="text" ng-model="qItem.question" class="form-control" id=""></div>
{{question}}
<div class="form-inline col-md-10 col-md-offset-2">
<div class="form-group" ng-repeat="items in qItem.options track by $index">
<label>{{$index+1}}</label><input ng-model="items.values" type="text" class="form-control" id="">
<i class="fa fa-plus-square" ng-click="addoptionsVo(items)"></i>
<i class="fa fa-minus-square" ng-click="optionsVo.splice($index, 1)"></i>
</div>
<div class="clearfix"></div>
<div class="btn-margin"><button class="btn btn-primary" ng-click="addoptionsVo($index)">Add Option</button></div>
</div>
<div class="clearfix"></div>
</div>
<div class="pull-left header-padding"><button class="btn btn-primary" ng-click="addquestionVo($event)">Add Question</button></div>
<div class="pull-right header-padding"><button class="btn btn-primary">Save</button></div>
</div>
</body>

Remove item from array in Vue

I have the following task list app. I am trying to implement a delete function. I get I need to use splice to remove the item from the array but how do I target only the item whose button I clicked on?
https://jsfiddle.net/clintongreen/txtrage5/1/
JS
new Vue({
el: '#tasks',
data: {
message: 'Tasks',
completed: null,
newTaskName: '',
tasklist: [
{ description: 'Read', completed: true },
{ description: 'Write', completed: true },
{ description: 'Edit', completed: false },
{ description: 'Publish', completed: false }
]
},
methods: {
completeTask: function(task){
// console.log(this.tasks.description);
task.completed = true;
},
newTask: function(){
this.tasklist.push({description: this.newTaskName, completed: false});
},
removeTask: function(task){
this.tasklist.splice(this.task.index, 1);
}
}
})
HTML
<div class="container" id="tasks">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{{ message }}
</h3>
</div>
<ul class="list-group">
<li class="list-group-item clearfix" v-for="task in tasklist" >
{{ task.description }}
<!-- <button class="btn btn-primary btn-sm pull-right" v-if="!task.completed" #click="completeTask(task)">Complete</button> -->
<div class="btn-group btn-group-sm pull-right" role="group" v-if="!task.completed">
<button type="button" class="btn btn-primary" #click="completeTask(task)">Complete</button>
<button type="button" class="btn btn-info">Edit</button>
<button type="button" class="btn btn-danger" #click="removeTask(task)">Delete</button>
</div>
<button class="btn btn-default btn-sm completed text-muted pull-right disabled" v-else>Completed</button>
</li>
<li class="list-group-item clearfix">
<input v-model="newTaskName" #keyup.enter="newTask" type="text" class="pull-left">
<button class="btn btn-success btn-sm pull-right" #click="newTask">Add Task</button>
</li>
</ul>
</div>
</div>
Use the index of the task in the v-for to decide which item to splice():
v-for="(task, index) in tasklist"
Your button:
<button type="button" class="btn btn-danger" #click="removeTask(index)">Delete</button>
And then simply:
removeTask: function(index) {
this.tasklist.splice(index, 1);
}
removeTask: function(task){
this.tasklist.splice(this.tasklist.indexOf(task), 1);
}
For Vue2 use delete. See API.
removeTask: function(index){
this.$delete(this.tasklist, index)
}
You can use indexOf to get the current index from the array
remove: function (task){
this.tasklist.splice(this.tasklist.indexOf(task),1);
},

Categories

Resources