I am using the datatables plugin from jquery and I have added to my datatable a button. When pressing the button I would like to add the elements title to an unordered list element.
Find below my minimum viable example:
const results = {
"generalInfo": [{
"title": "title1",
"permalink": "www.link.com",
"manufacturer": "manufacturer1",
"img": "https://images-na.ssl-images-test.com/images/asdfIdR/5adf1vELadfZeiMML.jpg",
"curreny": "$",
"price": "64.00",
"availability": "Usually ships in 24 hours",
},
{
"title": "title2",
"permalink": "www.link.com",
"manufacturer": "manufacturer2",
"img": "https://images-na.ssl-images-test.com/images/I/51adfkLhadsfgACH0L.jpg",
"curreny": "$",
"price": "59.99",
"availability": "Usually ships in 24 hours",
}
]
}
//transform data set
let dataSet = results.generalInfo.map((item, i) => [
i + 1,
`<img src="${item.img}" alt="${item.title}" height="42" width="42">
<a href="<?php the_permalink();?>">
${item.title}
</a>`,
item.manufacturer,
`<div>${item.currency} ${item.price}</div>`,
item.availability,
`<button id="addButton" type="button" onClick="${this.addToResults.bind(item)}">
Add
</button>`,
`<a class="btn btn-primary" target="_blank" role="button">
Buy
</a>`
])
$('#table_id').DataTable({
data: dataSet,
destroy: true,
columns: [{
title: "#"
},
{
title: "Title"
},
{
title: "Manufacturer"
},
{
title: "Price"
},
{
title: "Availability"
},
{
title: ""
},
{
title: ""
}
]
})
function addToResults(item) {
$("ul").append(`<li>${item.title}</li>`);
}
<link href="http://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<table id="table_id" class="display" style="width:100%"></table>
<h1>Results:</h1>
<ul>
</ul>
When I press the button I get the an error message and the text is not appended.
Any suggestions what I am doing wrong?
Instead of binding the item to your inline JS handler (which I really discourage people from doing, because inline JS is just plain bad), what you actually want is simply a reference back to the results.generalInfo array so that you can pull the correct item out from it.
In that case, this should suffice:
Assign a class, not an ID (IDs must be unique) to your button, say <button class="addButton" ... />.
Store an unchanging reference to the item in question. This is as simple as storing the index in the data- attribute, e.g. <button data-item-index="${i}" class="addButton" ... />
Bind a click event handler to that class
In the click event handler, retrieve the value from data-item-index and use it as a key to access the original item found in results.generalInfo. Remember that data- attributes always return string , so use the + operate to force cast it to an integer:
$('#table_id').on('click', 'button.addButton', function() {
const itemIndex = +$(this).data('item-index');
const item = results.generalInfo[itemIndex];
$("ul").append(`<li>${item.title}</li>`);
});
See proof-of-concept snippet below:
const results = {
"generalInfo": [{
"title": "title1",
"permalink": "www.link.com",
"manufacturer": "manufacturer1",
"img": "https://images-na.ssl-images-test.com/images/asdfIdR/5adf1vELadfZeiMML.jpg",
"curreny": "$",
"price": "64.00",
"availability": "Usually ships in 24 hours",
},
{
"title": "title2",
"permalink": "www.link.com",
"manufacturer": "manufacturer2",
"img": "https://images-na.ssl-images-test.com/images/I/51adfkLhadsfgACH0L.jpg",
"curreny": "$",
"price": "59.99",
"availability": "Usually ships in 24 hours",
}
]
}
//transform data set
let dataSet = results.generalInfo.map((item, i) => [
i + 1,
`<img src="${item.img}" alt="${item.title}" height="42" width="42">
<a href="#">
${item.title}
</a>`,
item.manufacturer,
`<div>${item.currency} ${item.price}</div>`,
item.availability,
`<button class="addButton" type="button" data-item-index="${i}">
Add
</button>`,
`<a class="btn btn-primary" target="_blank" role="button">
Buy
</a>`
]);
$('#table_id').on('click', 'button.addButton', function() {
const item = results.generalInfo[+$(this).data('item-index')];
$("ul").append(`<li>${item.title}</li>`);
});
$('#table_id').DataTable({
data: dataSet,
destroy: true,
columns: [{
title: "#"
},
{
title: "Title"
},
{
title: "Manufacturer"
},
{
title: "Price"
},
{
title: "Availability"
},
{
title: ""
},
{
title: ""
}
]
});
<link href="http://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<table id="table_id" class="display" style="width:100%"></table>
<h1>Results:</h1>
<ul>
</ul>
Related
I have a JSON list, which can have an array of "OrderLines" , within this array is other data such as part number, price etc...
I want to be able to print/display each "OrderLine" and its data in some HTML elements/tags, for each order-line the HTML elements are to be repeated, meaning I don't want e.g. all Part-Numbers to be in the SAME div tag, hopefully the code below will make sense as to what I want to achieve
{
"Depot": 4,
"DocumentType": "Sales Order",
"DocumentNumber": "123",
"OrderDate": "2022-06-23T09:09:12+01:00",
"OrderReference": "TEST",
"OrderedBy": "",
"ContactName": "",
"AccountCode": "EXAMPLE",
"CustomerName": "EXAMPLE",
"CustomerAddress1": "EXAMPLE",
"CustomerAddress2": "EXAMPLE",
"CustomerAddress3": "EXAMPLE",
"CustomerAddress4": "EXAMPLE",
"DepotVATNumber": "GB EXAMPLE",
"DeliveryName": "EXAMPLE",
"DeliveryAddress1": "EXAMPLE",
"DeliveryAddress2": "EXAMPLE",
"DeliveryAddress3": "EXAMPLE",
"DeliveryAddress4": "EXAMPLE",
"OrderLines": [
{
"PartNumber": "EXAMPLE",
"Description": "EXAMPLE",
"IncludeCostCodes": false,
"MaterialCode": "0",
"CostCentre": "",
"Quantity": 2,
"Price": 9.5,
"TotalAmount": 19,
"VATRate": 20
}
{
"PartNumber": "EXAMPLE 2",
"Description": "EXAMPLE 2",
"IncludeCostCodes": false,
"MaterialCode": "0",
"CostCentre": "",
"Quantity": 0,
"Price": 0,
"TotalAmount": 0,
"VATRate": 0
}
],
"TotalGoods": 19,
"TotalVat": 3.8,
"GrandTotal": 22.8
}
JQuery
<script>
let order = #Html.Raw(Model.Content);
$('.billaddN').text(order.CustomerName + "," );
$('.billadd1').text(order.CustomerAddress1 + "," );
$('.billadd2').text(order.CustomerAddress2 + "," );
$('.billadd3').text(order.CustomerAddress3 + "," );
$('.billadd4').text(order.CustomerAddress4);
$('.shippadd1').text(order.DeliveryAddress1 + "," );
$('.shippadd2').text(order.DeliveryAddress2 + "," );
$('.shippadd3').text(order.DeliveryAddress3 + "," );
$('.shippadd4').text(order.DeliveryAddress4);
$('.shippaddN').text(order.DeliveryName + "," );
$('.ordRef').text(order.OrderReference);
$('.ordNo').text(order.DocumentNumber);
$('.ordDate').text(order.OrderDate);
$('.ordBy').text(order.OrderedBy);
$('.subtotal').text("£" + order.TotalGoods);
$('.totalvat').text("£" + order.TotalVat);
$('.total').text("£" + order.GrandTotal);
$('.vatNo').text(order.DepotVATNumber);
$('.accountNo').text(order.AccountCode);
$(order.OrderLines).each(function(i,e) {
$(".order-lines-container").append(
'<tr>
<td width="80%">
<span class="font-weight-bold">order.PartNumber[i]</span>
<div class="product-qty">
<span class="d-block">order.Description[i]</span>
<span>Color</span>
</div>
</td>
<td width="20%">
<div class="text-right">
<span class="font-weight-bold">order.Price[i]</span>
</div>
</td>
</tr>'
)});
</script>
Your code is almost there, the issue you have is that your each() loop doesn't reference the specific line in the array you're iterating through.
In addition, the looping code can be simplified and made more performant by using map() to create an array of strings which you then append to the DOM just once.
Here's a working example:
var order = {Depot:4,DocumentType:"Sales Order",DocumentNumber:"123",OrderDate:"2022-06-23T09:09:12+01:00",OrderReference:"TEST",OrderedBy:"",ContactName:"",AccountCode:"EXAMPLE",CustomerName:"EXAMPLE",CustomerAddress1:"EXAMPLE",CustomerAddress2:"EXAMPLE",CustomerAddress3:"EXAMPLE",CustomerAddress4:"EXAMPLE",DepotVATNumber:"GB EXAMPLE",DeliveryName:"EXAMPLE",DeliveryAddress1:"EXAMPLE",DeliveryAddress2:"EXAMPLE",DeliveryAddress3:"EXAMPLE",DeliveryAddress4:"EXAMPLE",OrderLines:[{PartNumber:"EXAMPLE",Description:"EXAMPLE",IncludeCostCodes:!1,MaterialCode:"0",CostCentre:"",Quantity:2,Price:9.5,TotalAmount:19,VATRate:20},{PartNumber:"EXAMPLE 2",Description:"EXAMPLE 2",IncludeCostCodes:!1,MaterialCode:"0",CostCentre:"",Quantity:0,Price:0,TotalAmount:0,VATRate:0}],TotalGoods:19,TotalVat:3.8,GrandTotal:22.8}
let rows = order.OrderLines.map(line => `
<tr>
<td width="80%">
<span class="font-weight-bold">${line.PartNumber}</span>
<div class="product-qty">
<span class="d-block">${line.Description}</span>
<span>Color</span>
</div>
</td>
<td width="20%">
<div class="text-right">
<span class="font-weight-bold">${line.Price}</span>
</div>
</td>
</tr>`);
$(".order-lines-container").append(rows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table class="order-lines-container"></table>
I have API that stores JSON data as shown in JSON body below... I wanted to show the data amount stored in installments but it didn't work good because its showing me each amount value two times and I couldn't figure out the problem here.
{
"response": [{
"floors": [{
"flats": [{
"status": "sold",
"price": "150000",
"currency": "USD",
"end_date": "Not Set",
"buyer": "ella",
"buyer_phone_number": "002822128",
"receipt_number_field": "553108012022",
"size_unit": "M",
"_id": "61d9b61397e87e39832a5abb",
"flat_number": 1,
"description": "This is a newly created flat.",
"city": "NY",
"payment": {
"installment_payment": {
"installments": [{
"amount": "1344",
"date": "2022-01-13",
"is_paid": false
},
{
"amount": "444",
"date": "2022-01-24",
"is_paid": false
},
{
"amount": "44444",
"date": "2022-01-17",
"is_paid": false
}
],
"remaining": "150000"
},
"paid_amount": "1234"
},
"floor": "61d9b61397e87e39832a5aba",
"building": "61d9b61397e87e39832a5ab9",
"size": "176.25",
"directions": " south",
"createdAt": "2022-01-08T16:04:43.557Z",
"updatedAt": "2022-01-08T16:22:29.220Z",
"__v": 0
},
my code:
<div v-for="(flat,index) in Flats" :key="index">
<div v-for="(find,indexT) in flat.payment" :key="indexT" >
<div v-if="flat.payment.installment_payment">
<div v-for="(find,indexT) in flat.payment.installment_payment.installments" :key="indexT">
<div v-if="find.amount >0">
<p> {{find.amount}}$ amount </p>
</div>
</div>
</div>
</div>
</div>
p.S: I stored my API data in array Flats
This will probably work, but it's untested.
You generally do not want to use v-if inside of v-for; instead, you should filter the data first and use the result in the v-for loop. [reference]
Also, since each flat has an _id field, you can use that instead of the index for the top level :key attribute.
<div v-for="flat in flatsWithPayments" :key="flat._id">
<div v-for="(installment, index) in getInstallmentsWithPaymentGTZero(flat.payment.installment_payment.installments)" :key="index">
<p> {{installment.amount}}$ amount </p>
</div>
</div>
Obviously, replace Flats with your data, but also note that in order to compare the payment amount, it needs to be converted with either Number(), parseInt() or parseFloat()
// Flats = { ... }
export default {
computed: {
flatsWithPayments() {
return Flats.filter(f => f.payment != undefined)
}
},
methods: {
getInstallmentsWithPaymentGTZero(installments) {
return installments.filter(i => Number(i.amount) > 0)
}
}
}
I need to filter a list by their category, but each of these categories are custom, every user can write any category they want in the list.
I tried to make a list with ng-repeat in which I filtered all the duplicated values (In the code below is the unique:'Category' part), and I gave them the Category name as the value to filter, also I added an "All" category to show all the elements:
<ul class="categoriesList">
<li>
<label>
<input type="radio" ng-model="searchCategory.Category" value=""> All
</label>
</li>
<li ng-repeat="x in myList | unique:'Category'">
</label>
<input type="radio" ng-model="searchCategory.Category" value="{{x.Category}}"> {{x.Category}}
</label>
</li>
</ul>
But this approach isn't working. I've made a Plunker as example: Here is my plunker
I need to be able to add any category I want in the json example, and to be able of filter them. Thanks in advance.
OK the issue with your code was just that your property searchCategory was not defined on the $scope. Adding $scope.searchCategory = {}; to your controller will solve the issue. And the reason behind this is that ng-repeat creates its own child scope. Below is a snippet with the working solution.
Also one more thing was missing i.e you need to have the same group for all the radio buttons so that only one is selected at a time and that you do by adding name='filter' attribute all radio button.
var app = angular.module('app', []);
//duplicates filter
app.filter('unique', function() {
return function(items, filterOn) {
if (filterOn === false) {
return items;
}
if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
var hashCheck = {},
newItems = [];
var extractValueToCompare = function(item) {
if (angular.isObject(item) && angular.isString(filterOn)) {
return item[filterOn];
} else {
return item;
}
};
angular.forEach(items, function(item) {
var valueToCheck, isDuplicate = false;
for (var i = 0; i < newItems.length; i++) {
if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newItems.push(item);
}
});
// items = newItems;
}
return newItems;
};
});
app.controller('MainCtrl', function($scope) {
$scope.searchCategory = {};
$scope.myList = [{
"Category": "My custom category",
"Title": "Title example",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "My cat is named George",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "Hocus pokus",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "Tyrion Lannister must have been king",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "some text",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "7 projects going LIVE now",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "Batman vs Superman was a good movie",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "Youtube channel projects",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "Some project name",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "projects (more)",
"Comments": "Example comments"
},
{
"Category": "A different category",
"Title": "Remember, remember the fifth of november",
"Comments": "Hello there!"
},
{
"Category": "A different category",
"Title": "It's night, electric night",
"Comments": "General Kenobi"
},
{
"Category": "Custom category",
"Title": "project name again",
"Comments": "Example comments"
}
];
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Filter with custom values</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul class="categoriesList">
<li>
<label>
<input name="filter" type="radio" ng-model="searchCategory.Category" ng-value=""> All
</label>
</li>
<li ng-repeat="x in myList | unique:'Category'">
<label>
<input name="filter" type="radio" ng-model="searchCategory.Category" ng-value="x.Category"> {{x.Category}}
</label>
</li>
</ul>
<div class="wrapper" ng-repeat="y in myList | filter:searchCategory:true">
<ul class="click-text">
<li>{{y.Title}} - {{y.Comments}}</li>
</ul>
</div>
</body>
</html>
Hope this helps :)
You have to write Ex- name="rdoCategory" attribute for radio button
`<ul class="categoriesList">
<li>
<label>
<input type="radio" name="rdoCategory" ng-model="searchCategory.Category" value=""> All
</label>
</li>
<li ng-repeat="x in myList | unique:'Category'">
</label>
<input type="radio" name="rdoCategory" ng-model="searchCategory.Category" value="{{x.Category}}"> {{x.Category}}
</label>
</li>
</ul>`
After that it will work.
I have urls of images from flicker and I want to show them on screen but I can't get any images.
Here is my code:
loadimages(e) {
e.preventDefault();
this.setState({spinner:true});
console.log('spinner');
// axios.get(`https://www.pexels.com/`).then(res=>{
// console.log(this.state.spinner);
// this.setState({images:res.data,spinner:false});
// });
axios.get( "https://api.flickr.com/services/feeds/photos_public.gne?tags=kitten&format=json&nojsoncallback=true" )
.then((response) => {
console.log('hellodata', response.data.items);
this.setState({
images: response.data.items,
spinner:false
});
console.log('images', this.state.images);
})
.catch(function(err){
console.log(err);
})
}
render() {
const mappedStorage = this.state.images.map((item) => <li>{item.media.m}</li>)
return (
<div className="fun2">
{this.state.spinner ?
<div>
<MDSpinner size={50}/>
</div>
: null
}
{/* <ul>{mappedStorage} */}
<ul>
<img src={mappedStorage} />
</ul>
<button onClick={this.loadimages}>
Click Here
</button>
</div>
)
}
This is a sample response from the API:
{
"title": "Recent Uploads tagged kitten",
"link": "https://www.flickr.com/photos/tags/kitten/",
"description": "",
"modified": "2018-11-13T13:31:05Z",
"generator": "https://www.flickr.com",
"items": [
{
"title": "flo_02-10-06 001",
"link": "https://...",
"media": {
"m": "https://....jpg"
},
"date_taken": "2018-11-13T12:09:32-08:00",
"description": "......"
"published": "2018-11-13T11:11:06Z",
"author": "nobody#flickr.com (\"nikita zenon2\")",
"author_id": "125437611#N07",
"tags": "some tags here"
},
{
"title": "flo_02-10-06 002",
"link": "https://...",
"media": {
"m": "https://....jpg"
},
"date_taken": "2018-11-13T12:09:32-08:00",
"description": "......"
"published": "2018-11-13T11:11:06Z",
"author": "nobody#flickr.com (\"nikita zenon2\")",
"author_id": "125437611#N07",
"tags": "some tags here"
},
I get urls but now I don't now how to show images on screen, maybe by using map function. If you know, please let me know. I'm new in ReactJs.
Thanks
You're almost there actually, you just need to nest your img tags inside of the li tags.
<!-- language: lang-js -->
render() {
const mappedStorage = this.state.images.map((item) => <li><img src={item.media.m} /></li>)
return (
<div className="fun2">
{this.state.spinner?
<div>
<MDSpinner size={50}/>
</div>
:null}
<ul>{mappedStorage}<ul>
<button onClick={this.loadimages}>
Click Here
</button>
</div>
);
}
Hide table columns depend on button in multiple dynamic json array,when we click on color button we need to hide color column (Color value present in dimensioncheck key). I have created dynamic variable values in for loop,in myFunc trying to hide columns depend on variable status.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$filter) {
$scope.headers =
[{value:"color",hide:false},
{value:"fit",hide:false},
{value:"packagecontents",hide:false},
{value:"dimdim",hide:false},
{value:"style",hide:false},
{value:"title",hide:false},
{value:"wash care",hide:false}
];
$scope.checkObject=function(object,list){
/*var myRedObjects = $filter('filter')(list, { prod_value: "dismdim" });
console.log(myRedObjects);*/
var value =$filter('filter')(list, { dimensioncheck: object });
if(value && value.length>0)
return value[0].hide;
return null;
}
$scope.data = [
{
"check1": {
"condition": true,
"syntax": 7,
"prod_value": "dimdim",
"dimensioncheck": "color"
},
"check2": {
"list": true,
"prod_value": "Printed",
"dimensioncheck": "fit"
},
"check3": {
"list": true,
"prod_value": "Pack of 1",
"dimensioncheck": "packagecontents"
},
"check4": {
"list": true,
"prod_value": "Regular",
"dimensioncheck": "dimdim"
},
"check5": {
"condition": [true, true],
"syntax": true,
"prod_value": "White Printed Boxers ",
"dimensioncheck": "style"
},
"check6": {
"list": "Error in sets",
"prod_value": "White",
"dimensioncheck": "title"
},
"check7": {
"syntax": true,
"prod_value": "Hand Wash Cold Water, Dry Naturally, Do Not Iron Imprint directly, Do not Bleach.",
"dimensioncheck": "wash care"
}
}];
});
<html >
<head>
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.28/angular.js" data-semver="1.2.28"></script>
</head>
<body ng-app="plunker" ng-controller="MainCtrl">
<table class="dataTable" border="1" >
<tr>
<th ng-if="!cc.hide" ng-repeat = "cc in headers">{{cc.value}}
</th>
</tr>
<tr ng-repeat="current in data">
<td ng-if="!checkObject(key,headers)" ng-repeat="(key, val) in current">
<div class="colWrapper" ng-repeat="(inside_key, inside_values) in val">
<br/>
<span>{{inside_values}}</span>
</div>
</td>
</tr>
</table><br>
<span>
<div ng-repeat="header in headers">
<button ng-click="header.hide=!header.hide"><span ng-if="header.hide">Show </span><span ng-if="!header.hide">Hide </span>{{header.value}}
</button>
</div>
</span>
</body>
</html>
You should use the same object as in header array $scope.headers[0].hide. or incorporate headers object in $scope.data array.
You can also update both values
$scope.data = [
{
"check1": {
"condition": true,
"syntax": 7,
"prod_value": "dimdim",
"dimensioncheck": "color",
"hide":false
}
}]
<div class="colWrapper" ng-hide="inside_values.hide" ng-repeat="(inside_key, inside_values) in val">
<button ng-click="header.hide=!header.hide;$scope.data[0].check1.hide!=$scope.data[0].check1.hide">