How can i delete a row on fetch by onclick in reactjs - javascript

I am very new to this i dont know how to delete a row by using fetch.. ive already made a messed up code i don't know how it will work now please help me im so lost...
renderItem(d, i) {
return <tr key={i} >
<td> {d.Employee_ID} </td>
<td>{d.Employee_Name}</td>
<td>{d.Address }</td>
<td><center><button className ="btn btn-info" onClick={this.handleOnclick.bind(this, d.Employee_ID, d.Employee_Name, d.Address)} data-toggle="modal" data-target="#UpdateEmployee">Edit</button></center></td>
<td><center><button className ="btn btn-danger" onClick={this.deleteEmployee.bind(this, d.Employee_ID)}>Delete</button></center></td>
</tr>
}
handleOnclick(id,name,address) {
this.setState({
Employee_Name: name,
Address: address,
});
}
deleteEmployee(id) {
debugger
fetch ('http://localhost:5118/api/employeedetails/deleteemployeedetail/'+ id,
{ method: 'DELETE',})
.then(
res => this.setState({jsonReturnedValue : json})
)
.catch( err => cosole.error(err))
}

After deleting your element from api you also need to remove it from your state, Suppose you are rendering your table from state employee. then you need to do
deleteEmployee(id) {
debugger
fetch ('http://localhost:5118/api/employeedetails/deleteemployeedetail/'+ id,
{ method: 'DELETE',})
.then(
res => {
this.setState({jsonReturnedValue : json})
var employee = [...this.state.employee];
var idx = employee.findIndex(item => item.Employee_ID === id);
employee.splice(idx, 1);
this.setState({employee})
}
)
.catch( err => cosole.error(err))
}

Related

How to update a row with contenteditable in Vue?

I'm trying to figure out how to get the current changes in a 'contenteditable' and update it in the row that it was changed.
<tbody>
<!-- Loop through the list get the each data -->
<tr v-for="item in filteredList" :key="item">
<td v-for="field in fields" :key="field">
<p contenteditable="true" >{{ item[field] }}</p>
</td>
<button class="btn btn-info btn-lg" #click="UpdateRow(item)">Update</button>
<button class="btn btn-danger btn-lg" #click="DelteRow(item.id)">Delete</button>
</tr>
</tbody>
Then in the script, I want to essentially update the changes in 'UpdateRow':
setup (props) {
const sort = ref(false)
const updatedList = ref([])
const searchQuery = ref('')
// a function to sort the table
const sortTable = (col) => {
sort.value = true
// Use of _.sortBy() method
updatedList.value = sortBy(props.tableData, col)
}
const sortedList = computed(() => {
if (sort.value) {
return updatedList.value
} else {
return props.tableData
}
})
// Filter Search
const filteredList = computed(() => {
return sortedList.value.filter((product) => {
return (
product.recipient.toLowerCase().indexOf(searchQuery.value.toLowerCase()) != -1
)
})
})
const DelteRow = (rowId) => {
console.log(rowId)
fetch(`${import.meta.env.VITE_APP_API_URL}/subscriptions/${rowId}`, {
method: 'DELETE'
})
.then((response) => {
// Error handeling
if (!response.ok) {
throw new Error('Something went wrong')
} else {
// Alert pop-up
alert('Delete successfull')
console.log(response)
}
})
.then((result) => {
// Do something with the response
if (result === 'fail') {
throw new Error(result.message)
}
})
.catch((err) => {
alert(err)
})
}
const UpdateRow = (rowid) => {
fetch(`${import.meta.env.VITE_APP_API_URL}/subscriptions/${rowid.id}`, {
method: 'PUT',
body: JSON.stringify({
id: rowid.id,
date: rowid.date,
recipient: rowid.recipient,
invoice: rowid.invoice,
total_ex: Number(rowid.total_ex),
total_incl: Number(rowid.total_incl),
duration: rowid.duration
// id: 331,
// date: rowid.date,
// recipient: 'new R',
// invoice: 'inv500',
// total_ex: Number(500),
// total_incl: Number(6000),
// duration: 'Monthly'
})
})
}
return { sortedList, sortTable, searchQuery, filteredList, DelteRow, UpdateRow }
}
The commented lines work when I enter them manually:
// id: 331,
// date: rowid.date,
// recipient: 'new R',
// invoice: 'inv500',
// total_ex: Number(500),
// total_incl: Number(6000),
// duration: 'Monthly'
Each cell has content editable, I'm not sure how to update the changed event
The way these run-time js frontend frameworks work could be summarized as "content is the function of data". What I mean is the html renders the data that you send it. If you want the data to be updated when the user changes it, you need to explicitly tell it to do so. Some frameworks (like react) require you to setup 1-way data binding, so you have to explicitly define the data that is displayed in the template, as well as defining the event. Vue has added some syntactic sugar to abstract this through v-model to achieve 2-way binding. v-model works differently based on whichever input type you chose, since they have slightly different behaviour that needs to be handled differently. If you were to use a text input or a textarea with a v-model="item[field]", then your internal model would get updated and it would work. However, there is no v-model for non-input tags like h1 or p, so you need to setup the interaction in a 1-way databinding setup, meaning you have to define the content/value as well as the event to update the model when the html tag content changes.
have a look at this example:
<script setup>
import { ref } from 'vue'
const msg = ref('Hello World!')
</script>
<template>
<h1 contenteditable #input="({target})=>msg=target.innerHTML">{{ msg }}</h1>
<h2 contenteditable>{{ msg }}</h2>
<input v-model="msg">
</template>
If you change the h2 content, the model is not updated because vue is not tracking the changes. If you change through input or h1, the changes are tracked, which will also re-render the h2 and update its content.
TL;DR;
use this:
<p
contenteditable="true"
#input="({target})=>item[field]=target.innerHTML"
>{{ item[field] }}</p>

Send values from model as parameters in function

I have a view with a GridMVC and two buttons, in which I'm displaying several parameters of the model, and the buttons Edit or Delete the item in that row.
#Html.Grid(Model).Named("eventsGrid").Columns(columns =>
{
columns.Add(model => model.Summary)
.Titled("Nombre");
columns.Add(model => model.Description)
.Titled("Descripción");
columns.Add(model => model.StartDate)
.Titled("Fecha Inicio");
columns.Add(model => model.EndDate)
.Titled("Fecha Fin");
columns.Add()
.Sanitized(false)
.Encoded(false)
.SetWidth(30)
.RenderValueAs(model => (#Html.ActionLink("Editar", "EditEvent", "Home", new { eventId = model.EventID, calendarId = model.CalendarID }, new { #class = "btn btn-default" }).ToHtmlString()));
columns.Add()
.Sanitized(false)
.Encoded(false)
.SetWidth(30)
.RenderValueAs(model => (#Html.ActionLink("Borrar", "Delete", "Home", new { eventId = model.EventID, calendarId = model.CalendarID }, new {#class = "btn btn-default"}).ToHtmlString()));
What I want to do is that when I click the Delete button, an alert appears to confirm that you want to delete the item, so I made this function in a .js file:
function confirmDelete(EventID, CalendarID) {
if (confirm('¿Desea borrar este evento?'))
{
$.ajax({
url: '#Url.Action("Delete","Home")',
data: { eventId: EventID, calendarId: CalendarID }
})
} else {
// Do nothing!
}
}
I changed it to look like this:
.RenderValueAs(model => #<button onclick="confirmDelete('model.EventID','model.CalendarID')" class='btn btn-default'>Borrar</button>);
but this makes the values in the function literally model.EventID and model.CalendarID, and I can't use #model.EventID as it's already inside an #. I also tried with an answer from How to pass a model field to a Javascript function in a view?:
.RenderValueAs(model => #<button onclick="confirmDelete('" + model.EventID "')" class='btn btn-default'>Borrar</button>);
But this doesn't even call the function.
Which is the correct form to write the models parameters to make it work?
You can use an HtmlString:
.RenderValueAs(model => new HtmlString("<button onclick='confirmDelete(" + model.EventID + ", " + model.CalendarID + ")' class='btn btn-default'>Borrar</button>"));

How to create load more in search result with vue js and laravel

I want to create function load more in my search result with vue js and laravel.
This is what I try.
My form code to search
<form #submit.prevent="search">
<input v-model="term" type="search">
<button class="btn btn-success" type="submit">Search</button>
</form>
here is to show search result
<tr v-for="(result, index) in results.data">
<td>{{ result.artist_name }}</td>
<td>{{ result.gender }}</td>
<td>{{ result.created_at }}</td>
<td>{{ result.updated_at }}</td>
</tr>
<div v-if="results.next_page_url" class="card-footer">
<button #click.prevent="paginatesearch(results.next_page_url)" type="button">Load More</button>
</div>
here is my data variable
data() {
return {
term:'',
results:[],
}
},
Here is my code to showing search result.
search() {
let formData = new FormData();
formData.append('term', this.term);
axios.post('/api/artist/search/', formData)
.then((response) => {
this.SearchDiv = true;
this.IndexDiv = false;
this.results = response.data;
this.noResults = this.results.length === 0;
});
},
and this is my code to show load more data
paginatesearch(url = '') {
this.loading = true;
this.disabled = 1;
axios.get(url ? url : '/api/artist/search/')
.then(response => {
this.loading = false;
this.disabled = 0;
if (! this.results.data) {
this.results = response.data
}
else {
this.results.data.push(...response.data.data)
this.results.next_page_url = response.data.next_page_url
}
})
.catch(e => console.error(e))
},
But when I click the button, it give me
TypeError: Cannot convert undefined or null to object
Here is my full code if u need it https://github.com/jazuly1/nginx/blob/master/loadmorewithsearch.vue
'results'is defined as an array, but is used as an object.
just need a simple correction..
in search method change axios.post('/api/artist/search/', formData) to axios.post('/api/artist/search/' + this.$data.term)
and in paginatesearch method change axios.get to axios.post.
and some correction in controller page. now everything is working fine.

Trigger update action from checkboxfor with AnitForgeryToken from ajax call

I have this view that brings in all data from an entity:
#model MyApplication.Application.TableModel<Entities.FPDrinkingWater>
#{
Layout = null;
var insertionMode = InsertionMode.Replace;
var fail = "displayFailure";
var target = "UnverifiedDrinkingWatersContent";
var ajax = "UnverifiedDrinkingWaterLogLoader";
var verify = Html.UserHasClaim("FP/DrinkingWater/VerifyDrinkingWater");
var action = "VerifyDrinkingWater";
string form = action + "Form";
}
<br />
#if (Model != null && Model.Alert != null && Model.Alert.Message != null)
{
#Html.Alert(Model.Alert)
}
#MyHelper.Loader(ajax)
<div class="form-group">
<table id="UnverifiedDrinkingWaterTable" class="table table-hover">
<thead>
<tr>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().SID)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Location)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Replicate)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().CollectionDate)
</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().CollectionTime)
</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Collectors)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Clorinated)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Comments)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Verified)</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Data.Count(); i++)
{
using (Ajax.BeginForm(actionName: action, routeValues: null,
htmlAttributes: new { id = form, #class = "form-horizontal" },
ajaxOptions:
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = target,
OnSuccess = "success",
LoadingElementId = ajax
}))
{
#Html.AntiForgeryToken()
<tr>
<td>#Html.DisplayFor(m => m.Data[i].SID)</td>
<td>#Html.DisplayFor(m => m.Data[i].Location)</td>
<td>#Html.DisplayFor(m => m.Data[i].Replicate)</td>
<td>#Html.DisplayFor(m => m.Data[i].CollectionDate)</td>
<td>#Html.DisplayFor(m => m.Data[i].CollectionTime)</td>
<td>#Html.DisplayFor(m => m.Data[i].Collectors)</td>
<td>#Html.DisplayFor(m => m.Data[i].Clorinated)</td>
<td>#Html.DisplayFor(m => m.Data[i].Comments)</td>
<td>#Html.CheckBoxFor(v => v.Data[i].Verified, new {
data_url = Url.Action("VerifyDrinkingWater", "DrinkingWater"), id =
"checkboxid" }) </td>
</tr>
}
}
</tbody>
</table>
</div>
<hr />
#if (Model.Data.Count > 0)
{
<script>
$(document).ready(function () {
makeDataTable('UnverifiedDrinkingWaterTable');
});
(function () {
$('#checkboxid').change(function () {
var data = {};
data[$(this).attr('name')] = $(this).is('checked');
$.ajax({
url: $(this).data('url'),
type: 'POST',
data: data,
success: function (result) {
}
});
});
});
</script>
}
What my goal is that I want to update 3 fields on the record displayed in the table by checking the "Verified" checkbox. I followed This Link to enable a click event on the checkboxfor. However, I receive an error claiming that The required anti-forgery form field __RequestVerificationToken is not present.. This is the only error I receive.
So my question is, how can I combine the AntiForgeryToken creation by the Ajax call AND pass the checked status of the checkbox at the same time and then pass it to the controller? Right now it's not even touching the controller and just giving me the AntiForgeryToken Error.
just get the token using
var token = $('input[name="__RequestVerificationToken"]').val();
and put it in data like this
var data = {
__RequestVerificationToken: token
}
please note that you render the AntiForgeryToken multiple times, so modify your code to have the ability to get the right AntiForgeryToke of each form

Controller returns plain json data instead of staying on page

I'm trying to us an ajax request to return search results. When I submit the search it returns back my json data on a plain black and white page. How do I get it to stay on the page and act out the rest of my javascript? I think the problem is either event.preventDefault isn't working right or the return statement in the controller is stopping anything further from happening.
Here are my code snippets:
HTML
<div id="contactform">
<p>Search for a Contact</p>
{{ Form::open(array('route' => 'contacts.results', 'method' => 'post', 'id' => 'contactsearchform')) }}
{{ Form::text('contactsearch', null, array('id' => 'contactsearch', 'placeholder' => 'Name')) }}
<button type="submit">Search</button>
{{ Form::close() }}
</div>
<div id="search_results">
Search Results
<table cellpadding="0" cellspacing="0" border="0">
<thead>
<tr>
<td class="name first">Name</td>
<td class="phone">Phone</td>
<td class="email">Email</td>
<td class="lot">Lot</td>
<td class="edit last"></td>
</tr>
</thead>
<tbody>
<tr>
<td class="name first"></td>
<td class="phone"></td>
<td class="email"></td>
<td class="edit last"></td>
</tr>
</tbody>
</table>
</div>
Javascript
$('contactsearchform').submit(function(event) {
event.preventDefault();
var dataString = $(this).serialize();
console.log('Submitted Data:\n' + dataString);
$.ajax({
type: "POST",
url: "/contacts.results",
data: dataString,
error: function(){
console.log("Something is wrong. Please inform Admin");
},
success: function(resultData){
console.log('Result Data:\n' + resultData);
resultDataP = $.parseJSON(resultData);
console.log('Parsed Data:\n' + resultDataP);
if(resultDataP.table){
$('#search_results').html(resultDataP.table);
$('#search_results').fadeIn();
$('#contactsearchform input').blur();
}else{
console.log("Something didn't work.");
}
}
});
return false;
});
Controller
public function showSearch()
{
return View::make('portal.search');
}
public function doSearch()
{
// Search for contacts here
$search = Input::get('contactsearch');
$contacts = DB::table('contacts')->where('last_name', 'LIKE', "$search")->get();
if (count($contacts) != 0) {
$response = [
'status' => 'success',
'msg' => 'Contacts matched your search.',
'results' => $contacts
];
}
else {
$response = [
'status' => 'error',
'msg' => 'No contacts matched your search.'
];
}
return Response::json($response);
}
And my routes
// Search for contacts
Route::get( '/portal/contacts', array(
'as' => 'contacts.search',
'uses' => 'PortalController#showSearch'
) );
Route::post( '/portal/contacts', array(
'as' => 'contacts.results',
'uses' => 'PortalController#doSearch'
) );
you should change your javascript thing a bit use it like following
/** consider the hash before the id of form you haven't added one so its not considering the form
also you need to change the url of you $.ajax call put url:'/portal/contacts' because jquery don't understand name of laravel route
**/
$('#contactsearchform').submit(function(e){
........
});

Categories

Resources