i am doing a project to have a single page dynamically fill with some html code fetch from a DataBase. I'll post the code:
$.ajaxSetup({
async: false
});
$(document).on("click", "#all-book", function () {
console.log("hello JQ!");
$.getJSON("./books", function (data) {
console.log(data);
categories = getCategories();
var htmlAppend = ``;
$.each(data, function (key, value) {
var index = categories.findIndex(function (category) {
return category.id == value.category_id;
});
console.log(`index: ${index}`);
console.log(categories);
htmlAppend = htmlAppend + `
<button class="btn col-lg-4 col-md-6 col-sm-12" id="specific-book-button" type="button" value="${value.id}" onclick="">
<div class="card">
<img src="https://picsum.photos/id/233/400/250" class="card-img-top" alt="...">
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item">Title: ${value.title}</li>
<li class="list-group-item">Author: ${value.author}</li>
<li class="list-group-item">Category: ${categories[index].name}</li>
</ul>
</div>
</div>
</button>
`
});
$("#button-card").html(htmlAppend);
});
});
function getCategories(i) {
var x = null;
$.getJSON(`./categories`, function (data) {
console.log(data);
x = data;
});
return x;
}
basically it gets two dictionary with the .getJSON() methods but because is asynchronous ill have to put ajaxSetup with the async: false.
Is there a way to setu up ajax only for some specific methods? I'll want to have some other methods async or for example if the user want to change page does not have to wait the getJSON.
Thanks :)
Related
im trying to add an eventlistner to this html tag that i am creating with a api call
handleProducts()
function handleProducts() {
var display = document.getElementById("display")
var url = "http://127.0.0.1:8000/api/product/"
fetch(url)
.then((resp) => resp.json())
.then(function (data) {
console.log(data)
var products = data
for (var i in products) {
var product = `
<div class="col-lg-4">
<img class="thumbnail" src="${products[i].img}" alt="">
<div class="box-element product">
<h6><strong>${products[i].title}</strong></h6>
<hr>
<button data-product=${products[i].id} data-action = "add" class="btn btn-outline-secondary add-btn update-cart">Add to Cart</button>
<a class="btn btn-outline-success" href="">View</a>
<h4 class="price">${products[i].price}</h4>
</div>
</div>
`
display.insertAdjacentHTML('beforeend', product)
}
})
}
function handleAddToCart(){
var updateBtns = document.getElementsByClassName("update-cart")
console.log(updateBtns)
for (var y = 0; y < updateBtns.length; y++) {
updateBtns[y].addEventListener("click", function () {
console.log("Clicked")
})
}
}
handleAddToCart()
Ive included all the code because mabye there is something else i need to add when adding an eventlistner to this type of html code. The problem is that this does not console log clicked when i click the button. Any ideas?
You are calling both functions at the same time, and the fetch is not complete yet while you try to add the event listener. You can move the function call handleAddToCart() inside the first function after you create that element.
I have page ,where im showing all messages and in header im showing Total of messages by counting them and im looking for something with javascript or MVC ,when user click on link (its means message be opened) count one down (-1) of total count which is messages and then use localstorage or Cookies to remember the count for next time, when user coming back to check their messages.
Can anyone please help me or point me in the right direction!
Thanks in advance :)
For example : lets say i have 14 messages , when user click on link i should be 13
Controller:
public ActionResult Messages(RMAHistory m2)
{
string EmailID = Session["Email"].ToString();
ViewBag.CountMSG = (new DbNamespace().Besked.Where(x => x.KundensEmail == EmailID).Select(f => f.KundensEmail).ToList().Count);
var bla7 = (from RB in db.Besked
where RB.KundensEmail == EmailID
select new RMAHistory.Comment_List
{
id = RB.ID,
MSG = RB.MSG,
se = RB.Seen,
Date = RB.Date,
Forfatter = RB.Writer,
KundensEmail =RB.KundensEmail,
Id = RB.RMAID,
MSGType =RB.MSGType
});
m2.Comment_Lists = bla7.ToList();
return View(m2);
}
View:
<div class="col-lg-8 col-md-7 col-md-offset-2">
<div class="card">
<div class="card-header" data-background-color="purple">
<span class="category">(You have #ViewBag.CountMSG New Messages)</span>
</div>
<div class="content">
#if (!Model.Comment_Lists.Any())
{
<div class="bs-callout bs-callout-danger">
<h4>You Do not Have New Messages</h4>
</div>
}
else
{
foreach (var item in Model.Comment_Lists)
{
if (item.se == "Kunde")
{
<div class="bs-callout bs-callout-success message">
<div class="col-xs-3 text-right">
<a target="_blank" href="/Account/RMADetails?id=#item.Id" id="#item.id" class="btn btn-sm btn-success btn-icon btnChangestu"><i class="fa fa-envelope"></i></a>
</div>
<h4><i class="fa fa-bookmark-o" aria-hidden="true"></i> Message number #item.Id</span></h4>
<span class="text-muted"><small> #item.Date.ToString("dd/MMMM/yyy")</small></span><br />
<span class="text-muted status"><span> #item.MSGType</span></span>
<input type="hidden" name="ChangeStu" id="ChangeStu" value="read massage" />
</div>
}
}
}
</div>
</div>
</div>
JavaScript:
<script>
$(document).ready(function () {
$('.btnChangestu').click(function () {
var id = $(this).attr('id');
if (!id) {
return;
}
var button = $(this);
var status = $(this).closest('.message').find('.status');
$.ajax({
type: "POST",
url: '#Url.Action("UpdateMSGStatus", "Account")',
data: {
IDMSG: id,
ChangeStu: $("#ChangeStu").val()
},
dataType: 'json',
success: function (result) {
if (result) {
status.text("read message");
button.removeData('id')
console.log("Ok")
} else {
// display error?
console.log("error");
}
},
error: function () {
console.log('something went wrong - debug it!');
}
})
});
});
</script>
I have a basic live search built with jQuery ajax which searches through a JSON file from the server and outputs a list of events.
My script is set so that if the search text box has less than 2 characters, it should display the list of the events which were already displayed on the page prior to the user using the ajax search.
var currentEvents = $(".event-list-container").contents();
if(searchField.length < 2)
{
if(currentRequest != null) {
currentRequest.abort();
}
$('.event-list-container').empty();
$('.event-list-container').append(currentEvents);
}
The issue I am having is that if the user were to quickly empty the textbox (e.g. by doing CTRL + A & backspace), the currentEvents would display and then the ajax request after that and therefore remove the currentEvents and display the results for what was in the search textbox before the user had emptied it.
Below is the full script for this:
$(document).ready(function () {
var currentEvents = $(".event-list-container").contents();
var currentRequest = null;
var searchField;
var expression;
$.ajaxSetup({
cache: false
});
$('#refine-event-txtbox').keyup(function () {
searchField = $('#refine-event-txtbox').val();
expression = new RegExp(searchField, "i");
if(searchField.length < 2)
{
if(currentRequest != null) {
currentRequest.abort();
}
$('.event-list-container').empty();
$('.event-list-container').append(currentEvents);
}
else
{
searchEvents(currentRequest, searchField, expression);
}
});
function searchEvents(currentRequest, searchField, expression)
{
currentRequest = jQuery.ajax({
type: 'GET',
url: 'http://127.0.0.1:8000/api/events',
success: function(data) {
$('.event-list-container').empty();
$.each(data, function (key, value) {
if (value.title.search(expression) != -1 ||
value.location.search(expression) !=
-1) {
var startDate = value.startDate;
var startDateDay = moment.utc(startDate).format('D');
var startDateMonth = moment.utc(startDate).format('MMM');
var fullDate = moment.utc(startDate).format('D MMM YYYY');
var eventURL = "/events/" + value.id + "/" + value.title;
eventURL = eventURL.replace(/\s+/g, '-').toLowerCase();
$('.event-list-container').append(
`<div class="event-box">
<div class="row">
<div class="col-xs-12 col-sm-2 col-md-2 col-lg-1">
<div class="date">
<p class="day">${startDateDay}</p>
<p class="month">${startDateMonth}</p>
</div>
</div>
<div class="col-xs-12 col-sm-4 col-md-3 col-lg-3">
<div class="event-image">
<a href="${eventURL}">
<img class="img-responsive" src="${value.image}">
</a>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-7 col-lg-7">
<div class="event-details">
<h2 class="title">
${value.title}
</h2>
<p class="when"><span class="inline-title">When: </span>${fullDate} | ${value.startTime}-${value.finishTime}</p>
<p class="where"><span class="inline-title">Where:</span>${value.location}</p>
</div>
</div>
</div>
</div>
`);
}
});
},
error:function(e){
// Error
}
});
}});
As you can see inside the $('#refine-event-txtbox').keyup function if the search field length is set to less than 2, it should check to see if there is an ajax request and if so then abort it but the script is not doing this.
You can remove the reference of currentRequest from the function searchEvents.
Function Call:
searchEvents(searchField, expression);
And function:
function searchEvents(searchField, expression) {
.......
}
Try now..!
Figured it out. Adding the below to my ajax function as well as doing Shitole's answer seemed to do the trick.
beforeSend : function() {
if(currentRequest != null) {
currentRequest.abort();
}
},
I have an Ajax code like this:
$j(document).ready(function () {
function loading_show() {
$j('#loading').html("<img src='images/loading.gif'/>").fadeIn('fast');
}
function loading_hide() {
$j('#loading').fadeOut();
}
function loadData(page) {
loading_show();
$j.ajax({
type: "POST",
url: "load_data.php",
data: "page=" + page,
success: function (msg) {
var $response = $j(msg);
// Query the jQuery object for the values
oGlobal = $response.filter('#Z').text();
$j("#container").ajaxComplete(function(event, request, settings) {
loading_hide();
$j("#container").html(msg);
});
}
});
}
loadData(1); // For first time page load default results
$j('#container .pagination li.active').live('click', function () {
var page = $j(this).attr('p');
loadData(page);
});
});
Im getting this response:
<div id="container">
<div id="Z">JuanFernando</div>
<div id="q">
<div class="pagination">
<ul>
<li p="1" class="inactive">First</li>
<li class="inactive">Previous</li>
<li p="1" style="color:#fff;background-color:#006699;" class="active">1</li>
<li p="2" class="active">2</li>
<li p="2" class="active">Next</li>
<li p="2" class="active">Last</li>
</ul>
<input class="goto" size="1" style="margin-top:-1px;margin-left:60px;"
type="text">
<input id="go_btn" class="go_button" value="Go" type="button"><span class="total" a="2">Page <b>1</b> of <b>2</b></span>
</div>
</div>
</div>
I want to extract "JuanFernando" in order to show in div container but alone and I want that the rest of the response could be show in other different div for example: container2.
ajaxComplete is not what you want to use here, especially inside your success function. You want your success function to look something like this:
success: function (msg) {
loading_hide();
var $response = $j(msg);
// Query the jQuery object for the values
oGlobal = $response.find('#Z').text();
$j("#container").html(oGlobal);
$response.find('#Z').remove();
$j('<div id="container2"></div>').html($response.html()).appendTo('body');
}
We're just taking the oGlobal (which should be JuanFernando in this case) and sticking it in the #container. After that, remove the #Z div from the response, and stick the rest inside of a new #container2, and append it to the body, or wherever you'd like it.
Here's an "adapted" fiddle.
Basically the only thing that changes with you code is
replace
oGlobal = $response.filter('#Z').text();
with
oGlobal = $response.find('#Z').text();
also, see MattDiamant's answer concerning ajaxComplete.
I'm struggling with this 3 days and can't get my mind around why the first viewModel is working but second isn't , it even doesn't allow me console.log() anything.
My view Models and ko bindings:
// KO View Models
var indexViewModel = {
item: ko.observableArray([]),
cat: ko.observableArray([]),
loadcontent: function () {
alert("inside index function");
$.ajax({
url: '/api/item/all',
dataType: 'json',
success: function (data) {
var getArray = [];
$.each(data, function (index, item) {
getArray[index] = item;
});
indexViewModel.item(getArray);
}
});
$.ajax({
url: '/api/category/all',
dataType: 'json',
success: function (data) {
var getArray = [];
$.each(data, function (index, item) {
getArray[index] = item;
});
indexViewModel.cat(getArray);
}
});
}
};
var dataReal = null;
var itemViewModel = {
item: ko.observableArray([]),
loadcontent: function (getID) {
alert(getID);
$.ajax({
url: '/api/item/details/' + getID,
dataType: 'json',
success: function (data) {
var getArray = [];
$.each(data, function (index, item) {
getArray[index] = item;
});
itemViewModel.item(getArray);
dataReal = data;
},
error: function (xhr, status) {
switch (status) {
case 404:
alert('File not found');
break;
case 500:
alert('Server error');
break;
case 0:
alert('Request aborted');
break;
default:
alert('Unknown error ' + status);
}
}
});
}
};
var mainViewModel = {
indexPage: indexViewModel,
itemPage: itemViewModel
};
ko.applyBindings(mainViewModel);
My working HTML:
<div id="index-content" data-bind="init: mainViewModel.indexPage.loadcontent(), with: mainViewModel.indexPage">
<div class="item-list" data-bind="foreach: item">
<div class="item-container clearfix">
<div class="item-content clearfix">
<div class="title" data-bind="text: Title">
</div>
<div class="left-side clearfix">
<div class="item-image" data-bind="style: { backgroundImage: 'url(content/u/'+Image+')' }">
</div>
<div class="item-descr">
<div class="body" data-bind="text: Body">
</div>
<div class="item-more-details">
Vairāk...
</div>
</div>
</div>
And the HTML witch even ignores my console.log() calls:
#{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
int id = ViewBag.id;
}
<div id="item-details-content">
<input type="hidden" id="item-id" value="#id" data-bind=""/>
<div class="item-list" data-bind="init: itemPage.loadcontent(#id), with: itemPage.item">
<div class="item-container clearfix" data-bind="init: console.log($root)">
<div class="item-content clearfix">
<div class="title" data-bind="text: Title">
</div>
<div class="left-side clearfix">
<div class="item-image" data-bind="style: { backgroundImage: 'url(content/u/'+Image+')' }">
</div>
<div class="item-descr">
<div class="body" data-bind="text: Body">
</div>
<div class="item-more-details">
Vairāk...
</div>
</div>
</div>
Questions
What am I doing wrong?
Where is syntax errors?
How can I get console.log() working there?
Maybe there is an alternative to my problem, maybe I'm misunderstanding the concept of KO.js?
Conclusions
I know there is data inside mainViewModel.itemPage.loadcontent($.ajax(data)) because alert() shows it, but it doesn't pass the value to item!
I'm a newbie, total newbie, and if I thought I'am somewhat a decent programmer now I think I am total dumb ass and I am starting to hate KO.js, but I need it very badly!
NOTE: You can see in debug section that index page works just fine.
DEBUG PLACE
Here is published web application
And here is single item page
THANK YOU
Thanks everyone for helping me, I was so frustrated that I even didn't see any more the obvious, thanks again! Cheers!
1) At first glance, I noticed your HTML bindings are referring to mainViewModel. For example:
data-bind="init: mainViewModel.itemPage.loadcontent(#id), with: mainViewModel.itemPage.item
should likely be
data-bind="init: itemPage.loadcontent(#id), with: itemPage.item
You are already bound to mainViewModel
2) For debugging, use this to see what you are bound to in the view.
<pre data-bind="text:ko.toJSON(yourViewModelGoesHere, null, 2)"></pre>
3) The data being returned is not an array, though you are treating it as such.
$.ajax({
url: '/api/item/details/' + getID,
dataType: 'json',
success: function (data) {
var getArray = [];
$.each(data, function (index, item) {
getArray[index] = item;
});
itemViewModel.item(getArray);
dataReal = data;
},
If you create a sample at http://jsfiddle.net we can help you more.
Within the data-bind elements, you are referring to your model relative the the object you specified in the applyBindings() function. In your case, you called applyBindings(mainViewModel), so in the bindings themselves, you refer to its properties, not to mainViewModel itself.
In your non-working HTML, <div class="item-container clearfix" data-bind="console.log($root)"> seems suspicious. What kind of binding is this? It doesn't specify any particular property to bind.
Use your browser's developer tools (Firebug in Firefox, Developer Tools in Chrome/IE...) to see the syntax errors. If there are problems with bindings, you will see them there.