JQuery Ajax button isn't working - javascript

I am extremely new at writing ajax and working with a restful api... so, bear with me.
I have a Laravel 5.2 RESTful API that I am using on the backend, and I'm attempting to simply load a list of categories using Jquery / Ajax. As you click through the categories, each child category loads fine, but I cannot seem to get the "back" button to work (by this, I mean the LI I am generating, not the browser back button). When you click it, it shows the alert - and the data is correct, but that's it. The list doesn't refresh and populate with the appropriate items.
EDIT
There are no errors being thrown to the javascript console either. It just won't populate from the ajax call.
EDIT
I removed the request.abort() right after I made the original post.
EDIT
Here is the JSON returned from the URL api/categories/4 - as an example.
[{"id":6,"parent":4,"name":"sub_subcat4_1","slug":"sub_subcat4_1","description":null,"created_at":null,"updated_at":null},{"id":7,"parent":4,"name":"sub_subcat4_2","slug":"sub_subcat4_2","description":null,"created_at":null,"updated_at":null}]
EDIT
Here is the HTML for the #categories
<div class="row">
<div class="col-sm-12">
<ul id="categories">
</ul>
</div>
The Javascript
<script>
/*
* This loads the default / root categories.
*/
function getRootCategories() {
$.getJSON("api/categories", function(data) {
var categories = [];
$("#categories").html("");
$.each(data, function(key, val) {
$("#categories").append("<li class='subcat' data-id='" + val.id + "' onClick='getSubcats(this);'>" + val.name + '</li>');
});
});
}
/*
* This loads the sub categories if there's any data returned. Otherwise, just leave the user where they are.
*/
function getSubcats(cat) {
var dataID = cat.getAttribute("data-id");
alert(dataID);
if(dataID == "null") {
getRootCategories();
}
else {
$.getJSON("api/categories/" + dataID, function (data) {
if (data.length != 0) {
$("#categories").html("");
var newCats = '';
var parent = '';
$.each(data, function (key, val) {
parent = "<li class='subcat' data-id='" + val.parent + "' onClick='getSubcats(this);'>Back</li>";
newCats += "<li class='subcat' data-id='" + val.id + "' onClick='getSubcats(this);'>" + val.name + '</li>';
});
$("#categories").append(parent + newCats);
}
});
}
}
$(document).ready(function() {
$.ajaxSetup({ cache:false });
getRootCategories();
});
</script>

Ok, I just had my variables all mixed up. I wasn't setting the correct parent id.
The new script looks like this -
<script>
var previous = null;
/*
* This loads the default / root categories.
*/
function getRootCategories() {
$.getJSON("api/categories", function(data) {
var categories = [];
$("#categories").html("");
$.each(data, function(key, val) {
$("#categories").append("<li class='subcat' data-parent='" + val.parent + "' data-id='" + val.id + "' onClick='getSubcats(this);'>" + val.name + '</li>');
previous = val.parent;
});
});
}
/*
* This loads the sub categories if there's any data returned. Otherwise, just leave the user where they are.
*/
function getSubcats(cat) {
var dataID = cat.getAttribute("data-id");
previous = cat.getAttribute("data-parent");
if(dataID == "null") {
getRootCategories();
}
else {
$.getJSON("api/categories/" + dataID, function (data) {
if (data.length != 0) {
$("#categories").html("");
var newCats = '';
var parent = '';
$.each(data, function (key, val) {
parent = "<li class='subcat' data-id='" + previous + "' onClick='getSubcats(this);'>Back</li>";
newCats += "<li class='subcat' data-parent='" + val.parent + "' data-id='" + val.id + "' onClick='getSubcats(this);'>" + val.name + '</li>';
});
$("#categories").append(parent + newCats);
}
})
.fail(function(jqxhr, textStatus, error) {
console.log("Request Failed: " + textStatus + " - " + error);
});
}
}
$(document).ready(function() {
$.ajaxSetup({ cache:false });
getRootCategories();
});
</script>

Related

Error message on javascript after publishing azure website

I have a problem here whenever I debug my appication on localhost, it runs perfectly with no errors on the brower, but when I publish it on azure I get an error on the browser.
Here is the error i get:
/Service_Bind?depart_id=1:1 Failed to load resource: the server responded
with a status of 404 (Not Found)
Here is my source code on the view page for javascript:
<script>
$(document).ready(function () {
$('#depart').change(function () {
var id = $(this).val();
$('#Service').empty();
$.get('Service_Bind', { depart_id: id }, function (data) {
var v = '<option>---Select---</option>';
$.each(data, function (i, v1) {
v += '<option value=' + v1.Value + '>' + v1.Text + '</option>';
});
$('#Service').html(v).text();
});
});
$('#Gender').change(function () {
var id = $(this).val();
$('#Item').empty();
$.get('Item_Bind', { Gender_id: id }, function (data) {
var v = '<option>---Select---</option>';
$.each(data, function (i, v1) {
v += '<option value=' + v1.Value + '>' + v1.Text + '</option>';
});
$("#Item").html(v);
});
});
$('#Item').change(function () {
var id = $(this).val();
$('#price').empty();
$.get('Price_Bind', { Price_id: id }, function (data) {
var v = '<option>---Select---</option>';
$.each(data, function (i, v1) {
v += '<option value=' + v1.Value + '>' + v1.Text +
'</option>';
});
$('#price').html(v);
});
});
});
</script>
Here $.get('Service_Bind', { depart_id: id }, function (data) you are trying to call the api/method service_bind but you are not specifying the full url of that api.You need to add baseaddress as well.
For eg, my api is hosted on site www.contoso.com,then my url would be www.constoso.com/Service_Bind
This is what I was suppose to add on the script and it worked. The only problem was to fetch a page so the browser didn't know where was it fetching. Thanks for your help.
$.get('#Url.Action("Gender_Bind", "Request")', { Service_id: id }, function (data)

jQuery mobile mega dropdown adds more and more buttons

I am using a jquery plugin to generate a mega dropdown on my mobile website:
The menu is generated dynamically: everytime the user clicks on the right arrow, an api call is made to gather all sub-points to the clicked menu-entry. Down the menu everything works fine, but when I click on "back" it seems that there is added a forward/back-button for each menu-level:
This is my code:
// Catching the click-event
$(document).on('click','.next-button', function(){
var subCatContainer = $(this).next('.subcats');
var current = $(this).parent('.shopCatWithSub');
var categoryid = current.data('categoryuuid');
console.log('Next clicked');
console.log(categoryid);
if(typeof categoryid !== "undefined"){
buildSubcats(categoryid, subCatContainer, standardUrl);
} else {
console.log("No category set!");
}
});
// Get subcategories from API:
function buildSubcats(catid, subCatContainer, standardUrl) {
$.ajax({
type: 'GET',
url: 'https://my-awesome-url.de/api?category-id=' + catid,
dataType: 'jsonp',
contentType: 'application/json',
success: function (data) {
handleResponse(data, subCatContainer, standardUrl);
},
error: function(XMLHttpRequest, textStatus, errorThrow) {
console.log(errorThrow);
if (jQuery.isFunction(callback)) {
}
}
});
}
// Build and add new nav-elements:
function handleResponse(data, subCatContainer, standardUrl){
var output = '';
$.each(data, function(key, category){
var element = '';
var uladd = "";
var aClassAdd = "";
if(category.hasSubcategories) {
uladd = '<ul class="subcats"></ul>';
aClassAdd = 'has-next-button';
}
element = '<li class="shopCatWithSub" data-categoryuuid="' + category.categoryUUID + '">'
+ '<a class="text-truncate menu-item ' + aClassAdd + '" href="' + standardUrl + category.categoryUUID + '">'
+ '<i class="icon-' + category.categoryIconClass + ' mr-2"></i>'
+ category.displayName
+ '</a>'
+ uladd
+ '</li>';
output += element;
});
subCatContainer.empty();
subCatContainer.html(output);
// Re-initialize menu
$('.nav-mobile').mobileMegaMenu();
}
I assume that there is a problem with the re-initializing of the complete menu-structure. But I can't figure out how to handle it.

Dynamic Menu Bar with Child Relation In MVC Ajax Call

Hi i am student working on a Project in MVC i am Creating Dynamic Menu bar i retrieve Main Menu successfully but all child menus are shown in Contact Us Dropdown menu
---------------------------
ID ParentID MenuName
---------------------------
1 NULL Home
2 Null Contact Us
3 2 Address
4 2 Place
5 1 Index
//html
<div id="menu">
<ul>
</ul>
</div>
//jquery code
function LoadMenubarSuccess(response) {
if (response != undefined && response != null && response.length > 0) {
var IncidentData = "<ul>";
$.each(response, function (index, Obj) {
if (Obj.ParentMenuID == null || Obj.ParentMenuID == 0) {
IncidentData += "<li>"
+ "<a href='" + Obj.Url + "'>" + Obj.MenuName + "</a>"
}
if (Obj.ParentMenuID == !null || Obj.ParentMenuID > 0) {
IncidentData += "<ul>"+"<li>" + "<a href='" + Obj.Url + "'>" + Obj.MenuName + "</a>" +"</li>"+ "</ul>"
}
});
IncidentData +="</li>"+"</ul>";
$("#menu").html(IncidentData.replace(/null/g, ' - '));
}
}
The Loop is wrong.
You will have to first, sort your data to your needs.
In this case, it's probably best to loop through the items and attach the ones with parentID to the main item.
After that, start another loop which will create the actual menu.
// Sort could work like this
var menuList = [];
$.each(response, function(index, object) {
if(object.ParentID != null && object.ParentID != undefined)
menuList[object.ID].Children.push(object);
else
menuList[object.ID] = { Menu = object, Children = [] };
});
This way the data will be sorted to your needs (I did not test run this code).
After that, you can just do whatever you need with it. For example:
$incidentData = "<ul>";
$.each(menuList, function(index, parent) {
$incidentData = $incidentData + "<a href='" + parent.Url + "'>" + parent.MenuName + "</a>";
if(parent.Children.length > 0) {
$.each(parent.Children, function (childIndex, child) {
$incidentData = $incidentData + "<a href='" + child.Url + "'>" + child.MenuName + "</a>";
});
}
});
$incidentData = $incidentData + "</ul>";
Something like this should work.
You can see, we are sorting the data kinda like a tree.
Item has multiple parents and each parent can have multiple children.
This way, we don't have to do anything fancy. Perhaps you can change your source to do this for you?
Code is not tested. Adjust to your needs.

Drop last query in client side

I have a dropdown who populate depending of selected radio button:
JS
$(function getJsonProveedores() {
var items = "";
$('input[type=radio][name=editList]').change(function () {
if (this.value == 'Proveedor') {
$.getJSON("#Url.Action("GetProveedores", "Agenda")", function (data) {
$.each(data, function (index, item) {
items += "<option value='" + item.ID + "'>" + item.NombreComercial + "</option>";
});
$("#lstProveedor").html(items);
});
}
else if (this.value == 'Sucursal') {
$.getJSON("#Url.Action("GetUnidades", "Agenda")", function (data) {
$.each(data, function (index, item) {
items += "<option value='" + item.ID + "'>" + item.Nombre + "</option>";
});
$("#lstProveedor").html(items);
});
} else if (this.value == 'Usuario') {
$.getJSON("#Url.Action("GetUsuario", "Agenda")", function (data) {
$.each(data, function (index, item) {
items += "<option value='" + item.ID + "'>" + item.Nombre + "</option>";
});
$("#lstProveedor").html(items);
});
}
});
});
It load correctly all JSON, but I have an issue removing last query, for example if i click Proveedor radio, it load:
$.getJSON("#Url.Action("GetProveedores", "Agenda")"
and next if I click Sucursal radio, it load
$.getJSON("#Url.Action("GetUnidades", "Agenda")"
The problem is I keep seeing first query result of
$.getJSON("#Url.Action("GetProveedores", "Agenda")"
instead getting only second one:
$.getJSON("#Url.Action("GetUnidades", "Agenda")"
Controller:
public ActionResult GetProveedores()
{
var listaProveedores = db.Proveedores.ToList();
return Json(listaProveedores, JsonRequestBehavior.AllowGet);
}
public ActionResult GetUnidades()
{
var listaUnidades = db.Unidades.ToList();
return Json(listaUnidades, JsonRequestBehavior.AllowGet);
}
public ActionResult GetUsuario()
{
var listaUsuarios = db.Usuarios.ToList();
return Json(listaUsuarios, JsonRequestBehavior.AllowGet);
}
What can be the problem there? Regards
The way the functions/variables are structured, items never falls out of scope. So it never gets reset. Each subsequent AJAX call is simply appending to it.
Instead, get rid of the items variable from its current scope and use one local to each scope where you need it:
$(function getJsonProveedores() {
$('input[type=radio][name=editList]').change(function () {
if (this.value == 'Proveedor') {
$.getJSON("#Url.Action("GetProveedores", "Agenda")", function (data) {
var items = ""; // <--- declare it here
$.each(data, function (index, item) {
items += "<option value='" + item.ID + "'>" + item.NombreComercial + "</option>";
});
$("#lstProveedor").html(items);
});
}
else if (this.value == 'Sucursal') {
// ... and so on, declaring an "items" in each scope where you need it

JS Error with JSON Response Nodes

I have a page that generates a dropdown of options based on a prior selection. Once the parent dropdown is selected, that triggers a AJAX call which returns a JSON response of the child options.
function fetchLines(line) {
// Define vars we will use in this function
var dropdown = '';
// AJAX call to lines/sublines
$.ajax({
url: baseURL + "index.php/Project/fetchLines",
type: 'POST',
cache: false,
dataType: "json",
data: {
lineType: line
},
error: function(err) {
alert(err.statusText);
},
success: function(data) {
dropdown += '<option></option>';
$(data.lines).each(function() {
dropdown += '<optgroup label="' + this.line + '">';
if (this.sublines.options) {
$(this.sublines.options).each(function() {
dropdown += '<option value="' + this.subLine + '">' + this.subLine + '</option>';
});
}
dropdown += '</optgroup>';
});
$('[name=line]').empty().append(dropdown).select2("enable", true).trigger('change');
}
});
}
The issue I am running into is that there are some times no sublines in the JSON response which is causing the function to error out and not show results at all.
TypeError: this.sublines is undefined
JSON Response:
[
{
"line":"Business",
"sublines":{
"options":[
{
"subLine":"Accounts"
}
]
}
},
{
"line":"Consumer",
"sublines":{
"options":[
{
"subLine":"Cause"
},
{
"subLine":"Financial Services"
}
]
}
},
{
"line":"Risk"
}
]
Is there a way I can prevent a missing node subLines from breaking the function?
Ok, don't take it wrong, but it looks like you have no idea what you're doing. Just trying to use variables like they would be magically there.
I think this is what you're trying to do:
var dropdown = '<option></option>';
// iterate over your lines
$.each(data, function(i, line) {
// check id there's sublines (may be needed to check if there's options too)
if (line.sublines) {
// start an opt group only if there's sublines
dropdown += '<optgroup label="' + line + '">';
// iterate over it's options
$.each(line.sublines.options, function(j, option) {
// add the option to the html
dropdown += '<option value="' + option + '">' + option + '</option>';
});
// close the opt group
dropdown += '</optgroup>';
}
});
// replace the select content and trigger a change
$('[name="line"]').html(dropdown).select2('enable', true).trigger('change');
Check if subLine exists previously:
if (this.sublines.options) {
$(this.sublines.options).each(function() {
if (this.subLine)
dropdown += '<option value="' + this.subLine + '">' + this.subLine + '</option>';
});
}
Clearly in your JSON response not all objects from the array have the property sublines. And this is the line which is make the code to fail.
if (this.sublines.options) {
I'd suggest improving it to the following by checking if it has the property or not:
if (this.sublines && this.sublines.options) {
Check for sublines first...
if (this.sublines) {
if (this.sublines.options) {
$(this.sublines.options).each(function() {
dropdown += '<option value="' + this.subLine + '">' + this.subLine + '</option>';
});
}
}
I think you want to achieve something like this:
Fiddle: https://jsfiddle.net/a3bx77vm/3/
var dropdown = '';
for(var i = 0; i < data.length; i ++)
{
dropdown += '<option></option>';
var eachdata = data[i];
dropdown += '<optgroup label="' + eachdata.line + '">';
if(eachdata.sublines)
{
if (eachdata.sublines.options) {
$(eachdata.sublines.options).each(function() {
dropdown += '<option value="' + this.subLine + '">' + this.subLine + '</option>';
});
}
}
dropdown += '</optgroup>';
}
$("#dropdown").append($(dropdown));
The parsing was wrong because the data you get is an array, and it doesn't have property called lines.

Categories