svelte-sapper each block list item selection for deletion - get the id - sapper

I have a list of orders stored in a db. I use each block to display all orders with a delete button. When I click the delete button, I need to get the id of the CLICKED list item so I can look that order in the db and delete it. I don't know how to get the id of the CLICKED list item and pass it to handledelete function. How do I do that in svelte/sapper?
My code for the page that display all orders :
<script>
let orderz =[]
function handlesave() {
//save all the order data to db...
} // handlesave
function handleDelete () {
fetch('order', {
method: 'POST',
credentials : 'include',
headers: {
'Accept': 'application/json',
'Content-type' : 'application/json'
},
body: JSON.stringify({
// order id to send it to server to delete it from the db
})
}).then(response => response.json())
.then(responseJson => {
console.log("xxxxxxx:", responseJson.orderdetails )
})
.catch(error => console.log(error));
}
</script>
<form on:submit|preventDefault={handlesave}>
<button type="submit">Place Order</button>
</form>
<ul>
{#each orderz as order}
<li >
<p >{order.vendorid} - {order.vendorname} - {order.item}
- {order.price}</p>
<button on:click|once={handleDelete}>Delete</button>
</li>
{/each}
</ul>

You can tell the delete function which id was clicked by simply passing it in as an argument to the function:
function handleDelete(id) {
// Delete logic here
}
<button on:click="{() => handleDelete(id)}">Delete</button>
!! Note that you should not call handleDelete directly in your markup as this will execute the function immediately upon rendering (and thus effectively delete your entry as soon as it appears on screen)

Just add variable to your delete-function:
function handleDelete (id){
... use id to delete item in database...
}
Then add order id also to your on:click:
EDIT: on:click function call fixed as mentioned in other answer
<button on:click|once={()=>handleDelete(order.id)}>Delete</button>
There are other ways to do this, but this is the simplest one.
You don’t need once modifier, if you delete the item.
You will probably need a key with each-loop in order to keep list correctly updated after delete (key = thing.id in following example)
{#each things as thing (thing.id)}
<Thing current={thing.color}/>
{/each}
https://svelte.dev/tutorial/keyed-each-blocks

Related

How to show data of a single id using Vue js?

I'm displaying all records on a page at this URI xxx.test/employer/search/filter-by. I'm using Algolia Search to display all of the records/results. I added a button called View Profile and attached an empty method to it called showProfile.
When a user clicks on this button, I want to display this specific profile/record on a new page by itself. If I was fetching data on my own, i.e. without Algolia's code I would be able to do this, but in this case I'm not really sure how to do this.
EmployerSearchComponent.vue:
<ais-instant-search
:search-client="searchClient"
index-name="candidate_profiles"
>
<ais-search-box v-model="query" class="mb-3" placeholder="Search by job title, company name or city..." />
<ais-configure
:restrictSearchableAttributes="['job_title', 'employment_type']"
:hitsPerPage="25"
/>
<b-row class="job-search-card">
<ais-hits class="w-100">
<template slot="item" slot-scope="{ item }">
<b-col cols="12" class="mb-3">
<b-card>
<div class="float-right">
<i class="flaticon-paper-plane"></i> View Profile
</div>
<h4 style="margin-bottom: 20px;"><router-link to="/">{{item.job_title}}</router-link></h4>
<p>Type: {{item.employment_type}}</p>
<b-card-text class="mt-2"><span v-if="item.experience && item.experience.length < 300">{{item.experience}}</span><span v-else>{{item.experience && item.experience.substring(0,300)+"..."}}</span></b-card-text>
</b-card>
</b-col>
</template>
</ais-hits>
<ais-pagination />
</b-row>
</ais-instant-search>
If I click on the network tab in the console, and on the algolia query search URI, I can see that the search results are in results[0].hits. Below is a screenshot of this data.
P.S. My data is empty it just contains algolia client ID's.
How can I display a single id on a new page? I understand that I need to get the id from the record that is being displayed, and show this information on a new page, but I don't know how to put it all together.
Again I think I'll need a route, so I created this
Route::get('/employer/search/filter-by/show/{id}', 'EmployerSearchController#show')->name('employer.search.show');
I'm using Laravel for my backend. Thanks in advance.
------------------------------------- UPDATED: -------------------------------------
I feel like I'm really close, but $itemId in my controller after I die and dump returns "undefined" for some reason.
router.js (Vue Router):
{
path: '/employer/search/filter-by/:itemId/show',
name: 'employer-search-index',
component: SearchIndex,
meta: {
breadcrumb: 'Search Candidates',
requiresAuthEmployer: true,
employerHasPaid: true
},
},
EmployerSearchComponent.vue - with the <router-link> button:
<template slot="item" slot-scope="{ item }">
<b-col cols="12" class="mb-3">
<b-card>
<div class="float-right">
<router-link class="apply-job-btn btn btn-radius theme-btn apply-it" :to="'/employer/search/filter-by/' + item.id + '/show'">View Profile</router-link>
</div>
<h4 style="margin-bottom: 20px;"><router-link to="/">{{item.job_title}}</router-link></h4>
<p>Type: {{item.employment_type}}</p>
<b-card-text class="mt-2"><span v-if="item.experience && item.experience.length < 300">{{item.experience}}</span><span v-else>{{item.experience && item.experience.substring(0,300)+"..."}}</span></b-card-text>
</b-card>
</b-col>
</template>
EmployerSearchController.php:
public function show ($itemId)
{
$candidateProfiles = CandidateProfile::with(['user', 'photo', 'resume', 'video'])
->where('id', '=', $itemId)->get();
return Response::json(array(
'candidateProfiles' => $candidateProfiles,
), 200);
}
api.php:
Route::get('/employer/search/filter-by/{itemId}/show', 'EmployerSearchController#show')->name('employer.search.show');
And Finally, in the .vue file that shows the Full Single Profile, I'm loading the data like this.
mounted() {
this.loadCandidateProfileData();
},
methods: {
loadCandidateProfileData: async function () {
try {
const response = await employerService.loadCandidateProfileData();
this.candidateProfiles = response.data.candidateProfiles;
} catch (error) {
this.$toast.error("Some error occurred, please refresh!");
}
},
}
And the employerService.js file from the above code:
export function loadCandidateProfileData(itemId, data) {
return http().get(`employer/search/filter-by/${itemId}/show`, data);
}
As you suggest, you'll need an API endpoint to fetch the data from, returning it as a JSON object. You'll need to add a route to your client-side routes that takes the job ID (or slug) as a parameter. In your job component, you can retrieve the route param (e.g. in the created() method) as $route.params.id, for example, and use that to fetch the data from your API.
If your Algolia search is returning all the data that you want to display on your single job listing page, you could just put that in your Vuex store and display it without having to make another HTTP request. The downside of that would be that if a user bookmarked the page to return to later, there'd be no data in the store to display.
Thank you to Nilson Jacques responses. If you follow our conversation.
Finally I got the itemId param from the route and passed it to loadCandidateProfileData() like this:
loadCandidateProfileData: async function() {
try {
const itemId = this.$route.params.itemId;
const response = await employerService.loadCandidateProfileData(itemId);
this.candidateProfiles = response.data.candidateProfiles;
console.log(this.candidateProfiles);
if (response.data.candidateProfiles.current_page < response.data.candidateProfiles.last_page) {
this.moreExists = true;
this.nextPage = response.data.candidateProfiles.current_page + 1;
} else {
this.moreExists = false;
}
} catch (error) {
this.$toast.error("Some error occurred, please refresh!");
}
},

Django: populate modal with a form through Ajax

I´m trying to show a prepopulated form in a modal so users can click on an item, the modal opens showing a form with that item´s data that users can edit and save.
I can send data from a view to a modal with json serializer but I can´t find how to send a form.
When I test this, I get an error declaring that "Object of type FormularioTareas is not JSON serializable"
The problem seems to be clear, I can´t send the form through a json response. How can I handle this?
Thanks in advance!
The modal call in the template
<form name="form" action="#" id="form_tarea_{{tarea.id}}" method="POST">
{% csrf_token %}
<input name="id" id="tarea_id_submit" type="text" value="{{tarea.id}}" hidden="true"/>
<a href="" id="{{tarea.id}}" class="show_tarea" data-toggle="modal" >Este link</a>
</form>
The Ajax script
Here I´m using now $('#caca').text(tarea_data.caca); only to test I can send some info to the modal correctly. It works.
I guess I should update that "text" type to another one in order to work.
<script>
$(function(){
$('.show_tarea').on('click', function (e) {
e.preventDefault();
let tarea_id = $(this).attr('id');
$.ajax({
url:'/catalog/tareas-detail/',
type:'POST',
data: $('#form_tarea_'+tarea_id).serialize(),
success:function(response){
console.log(response);
$('.show_tarea').trigger("reset");
openModal(response);
},
error:function(){
console.log('something went wrong here');
},
});
});
});
function openModal(tarea_data){
$('#caca').text(tarea_data.caca);
$('#modal_tareas').modal('show');
};
</script>
The view
def TareaDetailView(request):
context = {}
tareas = Tareas.objects.values()
context[tareas] = Tareas.objects.all()
if request.method == 'POST' and request.is_ajax():
ID = request.POST.get('id')
tarea = tareas.get(pk=ID) # So we send the company instance
tareas_form = FormularioTareas(tarea)
caca = ID
return JsonResponse(tareas_form, safe=False)
else:
return render(request, 'catalog/artista.html', context)
Django forms are not json serializable. Either pass your model to json response or return your form as text/json.
return JsonResponse(serializers.serialize('json', tarea), safe=False)
I never use django or phyton before but I will try to help you:
First your ajax, try to use a done insteand of success, in this example you are getting info from some select to fill a form inside a modal with specific
function getData(clientId){
return $.ajax({
method: "POST",
url: "YourUrl",
data: { action: "SLC", clientId: clientId}
})
}
then you get your stuff:
getData(clientId).done(function(response){
//manage your response here and validate it
// then display modal, note: you must have some conditions to get the array
//and fill each input use JSON.parse to get the json array elements
openModal(response);
})
hope it helps

How to initialize select2 that uses a query for data when I already have a value

I have a view with 2 select boxes which are "cascading". A user selects a value from the first box and the second is populated based on the new value. This is done with Select2's query option, and works fine on the first load of the page. However, when I post the page and then render it, both select boxes already have values (say A and 1), but the dependent checkbox is not initialized. I have done a few things with initSelection and it didn't help much, sometimes just getting me into an loop.
What I am trying to do is this:
Link the two boxes
When the first box changes, reset the data in the second box and clear the value
When the page is re-drawn, and a value has already been selected (e.g. response to POST)
Go to server and get the data
Show the correct value for the existing <input type='hidden' value='xxx'>
if that value exists in the list, of course
if not, set value to blank (optionally fire jquery validation
Searching/constant querying is not needed. Just load once on change
I am thinking about changing this entire, so if this is really the wrong way to go about this, I'd be happy to know.
// caches ajax result based on `data`
// if data has been requested before, retrieves from the cache (nothing special)
// based on other code that did it all inside the `query` function directly
var locationsCache = new AjaxCacheClassThing( {
url: '...',
data: function() { return { masterId: $('#ParentBox').val(); } }
});
$(function() {
$('#ParentBox').change(function () {
$('#ChildBox').select2('data', null);
});
$('#ChildBox').select2({
query: locationsCache.queryCallbackHandler,
selectOnBlur: true,
});
});
The HTML uses the standard MVC helpers, and the HTML is rendered just fine.
#Html.DropDownListFor(m => m.ParentBox, SelectListOfStuff) // standard <select>
#Html.HiddenFor(m => m.ChildBox)
Here is how this scenario goes:
ParentBox is required (no empty option)
First Load: there is no value selected
Open the DependentBox
Ajax query issues correctly
Dropdown populates as expected
Second Load
Master box selects value just fine
ChildBox hidden input has value="xx" just fine
It does not show a selected item
Clicking dropdown populates the box as expected (from cache)
After some time spent, and lots of time on here and other places, I figured out how this all works (at least some parts of it!). Way simpler than I thought it was, but still surprised this isn't supported out of the box in some way. Seems like a really common request.
query and ajax and initselection aren't that useful in this scenario
They query each time a the search box changes (not desired)
They complicate everything
You need to init the select2 manually
If you use { data: ... } then you don't need query or ajax
Set the "value" on your hidden input if you have one, so the item gets selected
You have to recreate the box when you get new data
It is really simple. This is the simplest case, using no extra features or attributes
Javascript:
$(function() {
$('#ParentBox').change(createChildSelect2);
createChildSelect2();
});
function createChildSelect2() {
makeAjaxRequest( function( newData ) {
$('#ChildBox').select2( { data: newData } );
});
}
function makeAjaxRequest(callback) {
// calls a.jsp?parentId={?} and then the callback when done.
jQuery.ajax({
url: 'a.jsp', dataType: 'json',
data: function() {
return { parentId: $("#parentBox").val() };
}
})
.done(function (data) {
callback(data);
});
}
The HTML is all the same. A type=text and type=hidden both work:
<select id="ParentBox">
<option ... >
<option ... >
<select>
<input id="ChildBox" type="hidden" class="input-medium" value="1"/>
Or using Razor:
#Html.DropDownListFor(m => m.MasterBox, SelectListOfStuff) // standard <select>
#Html.HiddenFor(m => m.DependentBox)

codeigniter and tab contents

I have some tabs whose contents are fully functional parts of my website.
For instance, in my admin area, I have tabs [add/delete album][add photo][delete photo]. I'm technically dividing the admin area via tabs.
I'm using ajax to load the content into these tabs. tab content area is a div.
The view that is inside the tab content area also uses ajax to load stuff.
These are ajax calls that operates inside the tab content area.
Everything works fine as long as the view inside the tab content area stays same or only part of it changes. But when certain interactions inside tab content area return a whole new view, tab content area would not show them.
I know what happens is that this new view that is returned is not passed into the tab content area div.
In firebug, I can see that ajax success function response shows the new view that is returned.
But I do not know how to pass that new view to the tab content area.
I would appreciate it if someone could help me out in explaining how this could be solved or how contents inside tabs are managed in CI.
adminTabsview.php
<ul id="adminTabs">
<li ><?php echo anchor('#album_addDelete', 'Album Add/Delete'); ?></li>
</ul>
<div id="adminTabsContent"></div>
$(document).ready(function(){
$('#adminTabs a').on({
click: function (evt){
evt.preventDefault();
var page = this.hash.substr(1);
adminTabsAjaxCall(page);
}
});
});
function adminTabsAjaxCall ($data){
$.ajax({
type: "POST",
url: "index.php/adminsite_controller/"+ $data + "/",
dataType: "html",
data: $data,
statusCode: {removed}
},
success: adminTabContent
});
function adminTabContent (data){
$('#adminTabsContent').html(data);
}
albumsEditDeleteView.php
(this is a view that gets loaded into the tab contentarea div)
<div id="adminTabsContent">
<div id="albumList">
<ul>
<li>
Asdf
<a class="add" href="http://localhost/myPHP/photoalbums/index.php/Albums_Controller/add_album/301/Asdf/1/28/0">[ add ]</a>
<a class="delete" href="http://localhost/myPHP/photoalbums/index.php/Albums_Controller/delete_album/301/Asdf/1/28/0">[ delete ]</a>
</li>
</ul>
</div>
</div>
$(document).ready(function(){
$('#albumList').on({
click: function (evt){
evt.preventDefault();
var $clickedElement = evt.target.tagName;
if ($clickedElement == 'A' ){
var urlarray = url.split('/');
$chosen.albumid = urlarray[8];
$chosen.albumname = urlarray[9];
$chosen.lft = urlarray[10];
$chosen.rgt = urlarray[11];
$chosen.nodeDepth = urlarray[12];
if ($class == 'add'){
albumajaxcall($chosen);
}
if ($class == 'delete'){
deleteajaxcall($chosen);
}
}
}
});
});
function albumajaxcall($data){
$.ajax({
type: "POST",
url: "index.php/Adminsite_Controller/add_album/",
dataType: "json",
data: $data,
statusCode: {removed}
},
success: adminTabContent
});
}
function adminTabContent(data){
$('#adminTabsContent').html(data);
}
//heres the view file that has to replace the original view inside
//tabcontent area
//addnode_view.php
<?php echo form_open('Albums_Controller/update_albumSet');?>
<input type="text" name="newAlbum" id="newAlbum" value=""/>
<input type="submit" name="submit" value="Submit" />
<?php echo form_close();?>
<?php
//heres the controller function
function add_album(){
$levelData ['albumid'] = $this->input->post('albumid');
<!-- removed-->
$levelData ['main_content'] = 'addnode_view';
$this->load->view('includes/template', $levelData);
}
//And heres the controller method that loads
//the original page (albumsEditDeleteView.php) - this is the original view
//that gets loaded into the tab- I get stuck when this view
//has to be **totally** replaced through links in the view)
function album_addDelete(){
$allNodes ['myAlbumList'] = $this->Albums_Model->get_albumList();
echo $this->load->view('albumsEditDelete_view', $allNodes);
}
thanx in advance.
basically what you need to do is load whatever new view youll be putting in the tab in the controller function(adminsite_controller/whatever function) that is handling your ajax.
this will basically echo out the view file, which will be viewed as the success variable of your ajax function.
so you have something like this then for the success part of your ajax
success:function(msg){adminTabContent(msg);}
and in your controller in codeigniter you'll load a view the standard way, but since this will be only loading a piece of the page you may need to create a new view file thats just the div that will be there. You will do all your data gathering the same way you would if it wasn't ajax.
$data['some_data'] = $this->some_model->some_function();
$this->load->view('someview', $data);

Create google suggest effect with asp.net mvc and jquery

What I want to achieve, is not the autocomplete effect. What I want to achieve is that when you type on google the search results come up almost inmediately without cliking on a search button.
I already did the ajax example with a search button, but I would like it to make it work while you type it shows the results in a table.
The problem is I have no idea where to start.
EDIT: To ask it in another way.
Lets suppose I have a grid with 1000 names. The grid is already present on the page.
I have a textbox, that when typing must filter that grid using AJAX, no search button needed.
Thanks
Use a PartialView and jQuery.ajax.
$(document).ready(function () {
$("#INPUTID").bind("keypress", function () {
if($(this).val().length > 2) {
$.ajax({
url: "URL TO CONTROLLER ACTION",
type: "POST|GET",
data: {query: $("#INPUTID").val(),
success: function (data, responseStatus, jQXHR)
{
$("#WRAPPERDIVID").html(data);
}
});
}
});
});
Then in your view:
<div>
<input type="text" id="INPUTID" />
</div>
<div id="WRAPPERDIVID"></div>
Edit
Also, you could build in some sort of timer solution that submits the request after say 1 second of no typing, so you don't get a request on every key press event.
Theres a good example you can check here try to type 's' in the search
if thats what you want
then the code and the tutorial is here
another good example here
If you are working on "filtering" a set already located on the page, then you seem to want to set the visibility of the items in the list, based upon the search criteria.
If so, then first, you need to first establish your HTML for each item. You can use the following for each item:
<div class="grid">
<div class="item"><input type="text" value="{name goes here}" readonly="readonly" /></div>
{ 999 other rows }
</div>
Then, you must use some jquery to set each row visible/invisible based on the search criteria:
$("#searchBox").live("change", function () {
$("div[class='grid'] input").each(function () {
var search = $("#searchBox").val();
if ($(this).val().toString().indexOf(search) != -1)
$(this).parent().show();
else
$(this).parent().hide();
});
});
This will cause the visibility of each item to change, depending on whether or not the text in the search box matches any text in the item.

Resources