Delete nested object from array in Vue - ajax

trying to delete a nested object from an array. I've done some research and came across an example similar to mine, Vue.js Remove a Nested Object from Array.
However my issue is a slight more complex as I am trying to delete the object with ajax request. Essentially my engagement array contains nested objects of questions
so here is how I am displaying the list of questions for the engagement
<div v-for="question in engagement.questions" :key="question.id">
<div>
<div ">
{{ question.question }}
</div>
<div >
<span>Answered: </span>
<input type="checkbox" v-model="question.answered">
</div>
</div>
</div>
this is the button that will delete the question
<b-btn #click="deleteQuestion(engagement, question)">Confirm</b-btn>
and this is method that dispatches to the store
deleteQuestion(engagement, question) {
this.$store.dispatch('deleteQuestion', id)
.then(() => {
this.$router.push({path: '/engagement/' +this.engagement.id , query: {alert: 'The Question Was Succesfully Deleted'}});
})
},
and this is the store method
deleteQuestion(context, id) {
axios.delete('/questions/' + id)
.then(response => {
context.commit('deleteQuestion', id)
})
.catch(error => {
console.log(error)
})
},
Right now my alarm is getting “id is not defined” although I have other variations of this code where I will get a 500 internal server error which makes me think that I am not properly capturing the id of the question so it knows which one to delete…
below is the alarm I am getting in the console. I also did which is what the first arrow is pointing to for the observer
console.log(question)

the issue was that the b-model element that contained the #click="deleteQuestion" was outside of the div that contained the v-for so when I would click on the b-modal button it wasn't grabbing the id of the question. So I moved the b-modal to that div and it worked. Thank you for the help.
<div class="card mb-3" v-for="(question, index) in engagement.questions" :key="index">
<div class="card-header">
<div class="h6 m-0 justify-content-between d-flex">
<router-link class="btn btn-sm btn-primary mr-3" to="#" ><i class="far fa-edit mr-2"></i>Edit</router-link>
<b-btn class="outline-secondary" size="sm" v-b-modal.myQuestion><i class="fas fa-trash"></i><span class="ml-2">Delete</span></b-btn>
</div>
</div>
<div class="card-body bg-light d-flex justify-content-between">
<div class="h4 mr-5 text-left">
{{ question.question }}
</div>
<div class="ml-5 d-flex align-self-center">
<span class="font-weight-bold mr-2">Answered: </span>
<input class="mt-2" type="checkbox" v-model="question.answered">
</div>
</div>
<!-- this is the modal for deleting a question -->
<b-modal id="myQuestion" ref="myModalQuestion" hide-footer title="Delete Question">
<div class="d-block text-left">
<h5>Are you sure you want to delete question?</h5>
<br>
<p><strong>*Warning:</strong> Can not be undone once deleted.</p>
</div>
<div class="d-flex">
<b-btn class="mt-3" variant="danger" #click="hideModal">Cancel</b-btn>
<b-btn class="mt-3 ml-auto" variant="outline-success" #click="deleteQuestion(engagement, question.id)">Confirm</b-btn>
</div>
</b-modal>
</div>

Related

vuejs stop propagation of click when clicked outer div

I am trying to create a search show hide feature. I have a click event that shows the search bar, but if I click somewhere in the put it get removed again. I tried with click.stop but it doesn't work. I am using vue.js inside a laravel project.
Here is my code
<template>
<div>
<div class="menu_srch d-flex" #click.stop="dos">
<i class="fa fa-search search_btn"></i>
<div class="header_serch " v-if="showSearch">
<div class="header_serch_input">
<input type="" name="" placeholder="Search">
</div>
<div class="header_serch_i">
<i class="fa fa-search"></i>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
showSearch : false,
}
},
methods: {
dos(){
this.showSearch = !this.showSearch
}
},
}
</script>
using click.self doesn't even work.. dos method doesn't run when click.self is used.
Vue.js version : "^2.6.11"
You can capture the click event end to stop the propagation one level down.
<template>
<div>
<div class="menu_srch d-flex" #click="dos">
<i class="fa fa-search search_btn"></i>
<div #click.stop class="header_serch" v-if="showSearch">
<div class="header_serch_input">
<input type name placeholder="Search">
</div>
<div class="header_serch_i">
<i class="fa fa-search"></i>
</div>
</div>
</div>
</div>
</template>
Or you need to restructure your template.
<template>
<div>
<div class="menu_srch d-flex" #click="dos">
<i class="fa fa-search search_btn"></i>
</div>
<div class="header_serch" v-if="showSearch">
<div class="header_serch_input">
<input type name placeholder="Search">
</div>
<div class="header_serch_i">
<i class="fa fa-search"></i>
</div>
</div>
</div>
</template>

Custom Function call at controller not working

Grettings.
This is the first time I try to do my own function, and seems that something is wrong at the function calling because I only see a blank screen.
I want to make a search of a user, all that data will be displayed at the rigth when clicking the "Buscar" button. The data to look for is at the input control up the button (The image is atteched down).
This are my routes
Route::resource('escuelausuarios','EscuelaUsuariosController');
Route::get('registroaccesos/search/{$patron}', 'RegistroAccesosController#search')->name('registroaccesos.search');
Route::get('registroaccesos/otra/', 'RegistroAccesosController#otra')->name('registroaccesos.otra');
Route::resource('registroaccesos','RegistroAccesosController');
I send you the index function where the call is defined, with javascript. I guess there's something wrong with action
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">Grupos</a>
</nav>
<div class="container-fluid">
<div class="row">
<nav class="col-sm-2 d-md-block bg-light sidebar">
<div class="sidebar-sticky">
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Acciones</span>
<a class="d-flex align-items-center text-muted" href="#">
<span data-feather="plus-circle"></span>
</a>
</h6>
<div class="form-group">
<label for="strSearch" class="col-form-label">Patrón de búsqueda</label>
<select name="strSearch" class="form-control">
<option value="1" selected> Código del usuario</option>
<option value="2" > Nombre del usuario</option>
</select>
</div>
<div class="form-group">
<input placeholder="Patrón de búsqueda"
id="strPatron"
required
name="strPatron"
spellcheck="false"
class="form-control"
/>
</div>
<button class="btn btn-sm btn-outline-secondary"
onclick="
event.preventDefault();
document.getElementById('search-form').submit();
"
>Buscar</button>
<form id="search-form" action="{{ route('registroaccesos.otra' ) }}"
method="POST" style="display: none;">
<input type="hidden" name="_method" value="delete">
{{ csrf_field() }}
</form>
This is the function (otra) is being called when clicking "Buscar" Button.
public function search($patron="")
{
//
$patron = 'Hola';
dd($patron);
return;
}
public function otra()
{
//
dd(1);
return;
}
Seems the call is taking place when clicking "Buscar" button but as I told you, I only see a blank screen.
Help would be appreciated.
Thanks in advance.
You have created a route of GET request which is:
Route::get('registroaccesos/otra/', 'RegistroAccesosController#otra')->name('registroaccesos.otra');
You are submitting POST request through the form that's why it is unable to handle that request.
Try changing your GET request to POST as follows:
Route::post('registroaccesos/otra/', 'RegistroAccesosController#otra')->name('registroaccesos.otra');

Laravel 5.5 redirect to url with anchor and with data

In my footer.blade.php i have the following code about subscribing
<!--Subscription-->
#if(Session::has('success'))
<div class="form-group has-success">
<input class="form-control form-control-success" type="text" id="input-success">
<div class="form-control-feedback">{{ Session::get('success') }}</div>
</div>
#elseif(Session::has('failed'))
<div class="form-group has-danger">
<input class="form-control form-control-danger" type="text" id="input-danger">
<div class="form-control-feedback">{{ Session::get('failed') }}</div>
</div>
#else
{!! Form::open(['route'=>'subscribe.store', 'class' => 'subscribe-form', 'novalidate' => 'novalidate']) !!}
<div class="clearfix">
<div class="input-group input-light">
{!! Form::email('email', old('email'), ['class'=>'form-control ', 'placeholder'=>'Your e-mail']) !!}
<span class="input-group-addon"><i class="icon-mail"></i></span>
</div>
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true">
<input type="text" name="b_c7103e2c981361a6639545bd5_1194bb7544" tabindex="-1">
</div>
<button class="btn btn-primary" type="submit">
<i class="icon-check"></i>
</button>
</div>
{!! Form::close() !!}
<span class="form-text text-sm text-white opacity-50">Subscribe to our Newsletter to receive early discount offers, latest news, sales and promo information.</span>
#endif
In my controller i have the following function which receives the email and subscribes it correctly
public function registerNewsletter( Request $request )
{
$email = $request->input( 'email' );
$isSub = Newsletter::hasMember($email);
if($isSub) {
return redirect()->back()->with('failed', 'You have been already registered in our Newsletter system.');
} else {
Newsletter::subscribe($email);
return redirect()->back()->with('success', 'You have been registered in our Newsletter system.');
}
}
Although everything works good, i would like to page to scroll down to the footer because now it reloads and stays on top.
I've found the return redirect()->to(app('url')->previous(). '#hashid');
But there is no way to pass data among the id of the footer.
And also i've tried
return redirect()->back()->with('failed', 'You have been already registered in our Newsletter system.'). '#sitefooter';
and it didn't scroll down.
Any idea or workaround?
I've just tested this code. It will redirect you, scroll down to the anchor and will pass the data:
session()->flash('someVariable', $someData);
return redirect(url()->previous() . '#hashid');
To get stored data:
$someData = session('someVariable');
Or in a view:
{{ session('someVariable') }}

Collapse using Transition Vue

I would like to use Vue's collapse in my code, but I have an error.
[Vue warn]: <transition-group> children must be keyed: <p>
My component:
<template xmlns:v-model="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<section style="background-color: #dedede;">
<div class="container-fluid">
<div class="Consult-faq container">
<div class="row">
<div class="col-sm-12">
<h2>Cursos</h2>
<a v-for="(course,id) in courses" v-on:click="course.show = !course.show">
<a v-on:click="show = !show">
<div class="col-xs-12" style="border-bottom: solid;border-bottom-color: #999999;border-bottom-width:1px ">
<div class="col-xs-12">
<h4>
<i v-if="course.show" class="fa fa-plus-square text-right" aria-hidden="true"/>
<i v-else class="fa fa-minus-square text-right" aria-hidden="true"/>
{{course.text}}
</h4>
</div>
</div>
<transition-group name="fade">
<p v-if="show">
<div class="col-xs-12">
<article v-for="n in 2" class="Module-content">
<div class=" col-sm-12 col-md-6" style="position: relative;">
<div v-for="(course, index) in course.courses">
<course-card v-if="index % 2 == n - 1" :course="course"></course-card>
</div>
</div>
</article>
</div>
</p>
</transition-group>
</a>
</a>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
export default{
props : [
'courses'
],
data(){
return {
show: false
}
},
mounted() {
console.log(this.courses)
}
}
</script>
So, I'd like to know to collapse item per item. Like this in image.
When I click to expand, all courses expand or close all courses close.
Transition is irrelevant here (though you can get rid of that warning by using transition instead of transition-group, because the transition is only acting on a single node, not a group.)
Right now you're depending on a single variable show to control all of the elements' visibility, so they will all respond to clicks on any of them:
<a v-on:click="show = !show">
<p v-if="show" >
You need individual variables for each element if you want them to expand/collapse separately. You partially did this already, just change the remaining instances of show with course.show and you should be good to go.
(Probably want to clean up that nested <a> within <a> while you're at it; you can just remove the inner one.)
I solved this using vue-resource, I was using Guzzle in Laravel and require data in Controller make this not reactive. And I solved this problem using vue-resource in component.

Vue.js is not working when its in seperate file?

When i put my script code in seperate file in js then my component is not working, only when i directly write code in view. Any suggestion why is that happening?
https://jsfiddle.net/coligo/txpy7ug4/
<div id="app">
<div class="container-fluid">
<ul class="list-group">
<post v-for="comment in comments" :post="comment"></post>
</ul>
<div id="comment-box">
<div class="input-group">
<input type="text" class="form-control" placeholder="Enter a comment..." v-model="comment" #keyup.enter="postComment">
<span class="input-group-btn">
<button class="btn btn-primary" type="button" #click="postComment">Submit</button>
</span>
</div>
</div>
</div>
</div>
<template id="post-template">
<li class="list-group-item">
<i class="glyphicon glyphicon-chevron-up" #click="upvote" :class="{disabled: upvoted}"></i>
<span class="label label-primary">#{{ votes }}</span>
<i class="glyphicon glyphicon-chevron-down" #click="downvote" :class="{disabled: downvoted}"></i>
<a>#{{ post.title }}</a>
</li>
</template>
If your HTML is in different file than your JS code, You have to require that in your vue instance like explained here:
component.js
module.export = {
template: require('./templates/template.html'),
data: function(){
return {
text: "Hello World!"
};
}
};
template.html
<h1>{{ text }}<h1>

Resources