Sort Laravel pluck() by value not key? - javascript

I've got a form that has a few select elements populated by JSON. It looks something like below.
{
"suppliers":
{"1":"Amazon","2":"Apple"},
"manufacturers":
{"1":"Apple","2":"Lenovo"},
"categories":
{"2":"Tablet","3":"Laptop","4":"Desktop"},
"status":
{"1":"Ready to Deploy","2":"Deployed","3":"Damaged","4":"Destroyed"}
}
How can I sort by value (name) instead of the key (id)? I've tried everything I can think of and I've searched every phrase I can think of, but it's still not sorting alphabetically like I need. Note the orderBy below will sort it in the correct order if viewing the JSON directly in the browser, but in the form my select elements are still ordered by key.
public function getFormData()
{
$suppliers = DB::table('supplier')->orderBy('sup_name','asc')->pluck('sup_name','id');
$manufacturers = DB::table('manufacturer')->orderBy('man_name','asc')->pluck('man_name','id');
$categories = DB::table('category')->where('parent_id', 1)->orderBy('cat_name','asc')->pluck('cat_name', 'id');
$status = DB::table('status')->orderBy('status','asc')->pluck('status', 'id');
return json_encode(compact('suppliers', 'manufacturers', 'categories', 'status'));
}
Edit:
Using the following syntax from #Snapey I was able to get the sort order correct
public function getFormData()
{
$suppliers = DB::table('supplier')->orderBy('sup_name','asc')->get(['sup_name','id']);
$manufacturers = DB::table('manufacturer')->orderBy('man_name','asc')->get(['man_name','id']);
$categories = DB::table('category')->where('parent_id', 1)->orderBy('cat_name','asc')->get(['cat_name', 'id']);
$status = DB::table('status')->orderBy('status','asc')->get(['status', 'id']);
return json_encode(compact('suppliers', 'manufacturers', 'categories', 'status'));
}
New output:
{
"suppliers":
[{"sup_name":"Amazon","id":1},{"sup_name":"Apple","id":2}],
"manufacturers":
[{"man_name":"Apple","id":1},{"man_name":"Lenovo","id":2}],
"categories":
[{"cat_name":"Desktop","id":4},{"cat_name":"Laptop","id":3},{"cat_name":"Tablet","id":2}],
"status":
[{"status":"Damaged","id":3},{"status":"Deployed","id":2},{"status":"Destroyed","id":4},{"status":"Ready to Deploy","id":1}]
}
Unfortunately, now I get "object Object" in my select elements and the values are off.
Here's the function that builds my select elements:
function refreshData(newId, modalId) { //refreshes select elements on update
$.ajax({
url: '/json/collection.json',
type: 'GET',
dataType: 'json',
success: function(data) {
if(modalId){
switch(modalId){
case "supplierModal":
refreshSelect('inputSupplier', data.suppliers, newId);
break;
case "manufacturerModal":
refreshSelect('inputManufacturer', data.manufacturers, newId);
refreshSelect('inputManufacturerModel', data.manufacturers, newId); //modal window select
break;
case "statusModal":
refreshSelect('inputStatus', data.status, newId);
break;
case "categoryModal":
refreshSelect('inputCategory', data.categories, newId);
break;
}
}else{
refreshSelect('inputSupplier', data.suppliers);
refreshSelect('inputManufacturer', data.manufacturers);
refreshSelect('inputStatus', data.status);
refreshSelect('inputCategory', data.categories);
refreshSelect('inputManufacturerModel', data.manufacturers); //refresh modal window select element
}
}
});
}
function refreshSelect(name, data, newId) {
// Select by id
let $elem = $('#' + name);
// Get current value
let oldValue = $elem.val();
// Get option with value 0, which is the first element
let emptyOption = $elem.children('option').first();
// Empty the element and add the option. We are back to initial state
$elem.html(emptyOption);
// Append elements retrieved from backend
$.each(data, function(key, value) {
if(oldValue === key || newId === key){
$elem.append('<option value="' + key + '" selected="selected">' + value + '</option>');
}else{
$elem.append('<option value="' + key + '">' + value + '</option>');
}
});
if(newId){
$elem.val(newId);
}else{
$elem.val(oldValue);
}
}

Include the id as a named element rather that using it as the array index. For instance;
$suppliers = DB::table('supplier')->orderBy('sup_name','asc')->get(['sup_name','id']);
then in the json you will have an id attribute
Edit: for your additional question
something like
$.each(data, function(key, value) {
if(oldValue === value.id || newId === value.id){
$elem.append('<option value="' + value.id + '" selected="selected">' + value.sup_name + '</option>');
}else{
$elem.append('<option value="' + value.id + '">' + value.sup_name + '</option>'); } });
because now, each item in the array is an object with sup_name and id as attributes

The following will strip the key numbers out, and just leave you with an array that has your new ordering:
public function getFormData()
{
$suppliers = DB::table('supplier')->orderBy('sup_name','asc')->pluck('sup_name','id');
$suppliers = array_values($suppliers);
$manufacturers = DB::table('manufacturer')->orderBy('man_name','asc')->pluck('man_name','id');
$manufacturers = array_values($manufacturers);
$categories = DB::table('category')->where('parent_id', 1)->orderBy('cat_name','asc')->pluck('cat_name', 'id');
$categories = array_values($categories);
$status = DB::table('status')->orderBy('status','asc')->pluck('status', 'id');
$status = array_values($status);
return json_encode(compact('suppliers', 'manufacturers', 'categories', 'status'));
}

Related

Display Array Object With Jquery

I want displaying object data in table, which value inside name of object appear as <td>,
i have result in the network preview like this below:
I need displaying value inside A1_score and A2_score as <td>, so i tried jquery like this:
$(document).on('click', '#cektesting', function(e) {
$('.row').css({ 'visibility': 'hidden', 'display': 'none' });
$.ajax({
url: "pengguna/getCounting",
type: "GET",
dataType: "JSON",
success: function(data) {
$('.row').css({ 'visibility': 'visible', 'display': 'flex' });
$.each(data['A1_score', 'A2_score'], function(key, value) {
$('#tbodyres').append(
'<tr id="idscore"><td>' + key + '</td><td>' + value + '</td><td>' + value + '</td></tr> '
);
});
}
});
});
And last thing those data came from my Controller.php:
public function getCounting()
{
$get_row_class = $this->getdata->getAutism();
$get_row = $this->getdata->countrow();
$row_autism = $get_row_class['Autism'];
$row_normal = $get_row_class['Normal'];
$res_autism = number_format($row_autism / $get_row['jml_data_latih'], 6);
$res_normal = number_format($row_normal / $get_row['jml_data_latih'], 6);
$A_Score = $this->getdata->getA_score();
$data = [];
foreach ($A_Score as $as) {
$row['A_Y_NORMAL'] = $as['A1_YES_NORMAL'] / $row_normal;
$row['A_Y_AUTIS'] = $as['A1_YES_AUTIS'] / $row_autism;
$row['A_N_NORMAL'] = $as['A1_NO_NORMAL'] / $row_normal;
$row['A_N_AUTIS'] = $as['A1_NO_AUTIS'] / $row_autism;
$row2['A_Y_NORMAL'] = $as['A2_YES_NORMAL'] / $row_normal;
$row2['A_Y_AUTIS'] = $as['A2_YES_AUTIS'] / $row_autism;
$row2['A_N_NORMAL'] = $as['A2_NO_NORMAL'] / $row_normal;
$row2['A_N_AUTIS'] = $as['A2_NO_AUTIS'] / $row_autism;
$data['A1_score'] = $row;
$data['A2_score'] = $row2;
}
echo json_encode($data);
}
Result:
And this is what i get when i tried build jquery from jquery code above, So i get A2_score data but A1_score didn't displaying only A2_score data get looped.
You can get all keys inside your object and then use that keys to get required data from both JSON Object .
Demo Code :
//just for demo..
var data = {
"A1_score": {
"xs": 12322,
"sse": 1232
},
"A2_score": {
"xs": 1234,
"sse": 213
}
}
//get keys of one object because keys in other object are same
var keys = Object.keys(data["A1_score"])
console.log(keys)
//loop through keys
for (var i = 0; i < keys.length; i++) {
var keys_ = keys[i]
//add that inside your table
$('#tbodyres').append(
'<tr class="idscore"><td>' + keys_ + '</td><td>' + data["A1_score"][keys_] + '</td><td>' + data["A2_score"][keys_] + '</td></tr> '
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tbodyres"></table>
You can not use data['A1_score', 'A2_score'] to iterate over properties A1_score & A2_score. What you should do is iterate over either A1_score or A2_score and retrieve key. Then get values from A1_score & A1_score with data["A1_score"][key] & data["A2_score"][key].
Try like below.
$.each(data["A1_score"], function(key, value) {
$('#tbodyres').append(
'<tr id="idscore"><td>' + key + '</td><td>' + data["A1_score"][key] + '</td><td>' + data["A2_score"][key] + '</td></tr> '
);
});

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.

Append returned data to different elements based on objects names

How do you append json returned objects to different elements based on the object's name? My JSON data is bigger than the following example so I wonder if it's a good idea to use if statement in .ajax for each object:
JSON Example Data
[{"name":"Europe","year":"2000"},{"name":"Asia","year":"2001"},{"name":"Africa","year":"2002"}]
HTML
<div class="Europe"></div>
<div class="Asia"></div>
<div class="Africa"></div>
JS
$.ajax({
url: "text.json",
success: function (data) {
var item_html;
$(data).each(function (index, item) {
var name = item.name;
item_html='<h3>'+name+'</h3><div>'+item.year+'</div>';
});
if (name == Africa){
$('.Africa').append(item_html);
}
if (name == Europe){
$('.Europe').append(item_html);
}
if (name == Asia){
$('.Asia').append(item_html);
}
},
error: function () {$('.Europe').append("<b>No Results Returned</b>");}
});
Move your if block in each
$(data).each(function (index, item) {
var name = item.name;
item_html = '<h3>' + name + '</h3><div>' + item.year + '</div>';
if(name == 'Africa') {
$('.Africa').append(item_html);
}
if(name == 'Europe') {
$('.Europe').append(item_html);
}
if(name == 'Asia') {
$('.Asia').append(item_html);
}
});
I think since the name and class names are the same you can use it to find the target element within the .each() loop and set its content like
$.ajax({
url: "text.json",
success: function (data) {
var item_html;
$(data).each(function (index, item) {
var name = item.name;
$('.' + name).html('<h3>' + name + '</h3><div>' + item.year + '</div>')
});
},
error: function () {
$('.Europe').append("<b>No Results Returned</b>");
}
});

Can't create select element with returned json data from Ajax call

I'm making an ajax call to retrieve some JSON objects. I get them right. but the problem is when I want to create a select element from returned JSON, it doesn't create one or seemed to be.
My JavaScript so far:
jQuery("#make").change(function () {
var value = $(this).val();
jQuery.getJSON("<?php echo site_url('ajax/get/models'); ?>", {
makeId: value
},
function (data) {
if (data != "false") {
var modelsSelect = jQuery.createElement('select');
var modelsOptions = "";
var id;
var model
jQuery.each(data, function () {
jQuery.each(this, function (key, value) {
if (key == "id") {
id = value;
} else {
model = value;
}
});
modelsOptions += "<option value=" + id + ">" + model + "</option>"
});
modelsSelect.innerHTML = modelsOptions;
jQuery("#model").html = modelsSelect;
} else {
alert("false");
}
});
});
my returned JSON Format:
Object { id="28", model="test model"}
There could be n number of JSON objects in returned response from ajax call.
There is no createElement method in jQuery
jQuery.createElement should be document.createElement
Also no need to loop over the objects' properties, you can access them by the key directly
jQuery.each(data, function (index, item) {
modelsOptions += "<option value=" + item.id + ">" + item.model + "</option>"
});
Change this
jQuery("#model").html = modelsSelect;
to
jQuery("#model").html(modelsSelect);
Reference
.html()

Categories