Я хотел бы отображать продукты в горизонтальной форме, как показано в разделе «Желаемый вид», но сейчас они отображаются в вертикальной форме, как показано в разделе «Существующий вид».
См. скриншот желаемого вида ниже:
Код желаемого образа
магазин-compare.html
<main class = "main">
<div class = "page-header breadcrumb-wrap">
<div class = "container">
<div class = "breadcrumb">
<a href = "index.html" rel = "nofollow"><i class = "fi-rs-home mr-5"></i>Home</a>
<span></span> Shop <span></span> Compare
</div>
</div>
</div>
<div class = "container mb-80 mt-50">
<div class = "row">
<div class = "col-xl-10 col-lg-12 m-auto">
<h1 class = "heading-2 mb-10">Products Compare</h1>
<h6 class = "text-body mb-40">There are <span class = "text-brand">3</span> products to compare</h6>
<div class = "table-responsive">
<table class = "table text-center table-compare">
<tbody>
<tr class = "pr_image">
<td class = "text-muted font-sm fw-600 font-heading mw-200">Preview</td>
<td class = "row_img"><img src = "assets/imgs/shop/product-2-1.jpg" alt = "compare-img" /></td>
<td class = "row_img"><img src = "assets/imgs/shop/product-1-1.jpg" alt = "compare-img" /></td>
<td class = "row_img"><img src = "assets/imgs/shop/product-3-1.jpg" alt = "compare-img" /></td>
</tr>
<tr class = "pr_title">
<td class = "text-muted font-sm fw-600 font-heading">Name</td>
<td class = "product_name">
<h6><a href = "shop-product-full.html" class = "text-heading">J.Crew Mercantile Women's Short</a></h6>
</td>
<td class = "product_name">
<h6><a href = "shop-product-full.html" class = "text-heading">Amazon Essentials Women's Tanks</a></h6>
</td>
<td class = "product_name">
<h6><a href = "shop-product-full.html" class = "text-heading">Amazon Brand - Daily Ritual Wom</a></h6>
</td>
</tr>
<tr class = "pr_price">
<td class = "text-muted font-sm fw-600 font-heading">Price</td>
<td class = "product_price">
<h4 class = "price text-brand">$12.00</h4>
</td>
<td class = "product_price">
<h4 class = "price text-brand">$14.00</h4>
</td>
<td class = "product_price">
<h4 class = "price text-brand">$15.00</h4>
</td>
</tr>
<tr class = "pr_rating">
<td class = "text-muted font-sm fw-600 font-heading">Rating</td>
<td>
<div class = "rating_wrap">
<div class = "product-rate d-inline-block">
<div class = "product-rating" style = "width: 90%"></div>
</div>
<span class = "rating_num">(121)</span>
</div>
</td>
<td>
<div class = "rating_wrap">
<div class = "product-rate d-inline-block">
<div class = "product-rating" style = "width: 90%"></div>
</div>
<span class = "rating_num">(35)</span>
</div>
</td>
<td>
<div class = "rating_wrap">
<div class = "product-rate d-inline-block">
<div class = "product-rating" style = "width: 90%"></div>
</div>
<span class = "rating_num">(125)</span>
</div>
</td>
</tr>
<tr class = "description">
<td class = "text-muted font-sm fw-600 font-heading">Description</td>
<td class = "row_text font-xs">
<p class = "font-sm text-muted">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and</p>
</td>
<td class = "row_text font-xs">
<p class = "font-sm text-muted">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and</p>
</td>
<td class = "row_text font-xs">
<p class = "font-sm text-muted">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and</p>
</td>
</tr>
<tr class = "pr_stock">
<td class = "text-muted font-sm fw-600 font-heading">Stock status</td>
<td class = "row_stock"><span class = "stock-status in-stock mb-0">In Stock</span></td>
<td class = "row_stock"><span class = "stock-status out-stock mb-0">Out of stock</span></td>
<td class = "row_stock"><span class = "stock-status in-stock mb-0">In Stock</span></td>
</tr>
<tr class = "pr_weight">
<td class = "text-muted font-sm fw-600 font-heading">Weight</td>
<td class = "row_weight">320 gram</td>
<td class = "row_weight">370 gram</td>
<td class = "row_weight">380 gram</td>
</tr>
<tr class = "pr_dimensions">
<td class = "text-muted font-sm fw-600 font-heading">Dimensions</td>
<td class = "row_dimensions">N/A</td>
<td class = "row_dimensions">N/A</td>
<td class = "row_dimensions">N/A</td>
</tr>
<tr class = "pr_add_to_cart">
<td class = "text-muted font-sm fw-600 font-heading">Buy now</td>
<td class = "row_btn">
<button class = "btn btn-sm"><i class = "fi-rs-shopping-bag mr-5"></i>Add to cart</button>
</td>
<td class = "row_btn">
<button class = "btn btn-sm btn-secondary"><i class = "fi-rs-headset mr-5"></i>Contact Us</button>
</td>
<td class = "row_btn">
<button class = "btn btn-sm"><i class = "fi-rs-shopping-bag mr-5"></i>Add to cart</button>
</td>
</tr>
<tr class = "pr_remove text-muted">
<td class = "text-muted font-md fw-600"></td>
<td class = "row_remove">
<a href = "#" class = "text-muted"><i class = "fi-rs-trash mr-5"></i><span>Remove</span> </a>
</td>
<td class = "row_remove">
<a href = "#" class = "text-muted"><i class = "fi-rs-trash mr-5"></i><span>Remove</span> </a>
</td>
<td class = "row_remove">
<a href = "#" class = "text-muted"><i class = "fi-rs-trash mr-5"></i><span>Remove</span> </a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
Пожалуйста, смотрите скриншот Existing Look ниже:
Существующий код Look
view_compare.blade.php
<div class = "page-header breadcrumb-wrap">
<div class = "container">
<div class = "breadcrumb">
<a href = "index.html" rel = "nofollow"><i class = "fi-rs-home mr-5"></i>Home</a>
<span></span> Compare
</div>
</div>
</div>
<div class = "container mb-80 mt-50">
<div class = "row">
<div class = "col-xl-10 col-lg-12 m-auto">
<h1 class = "heading-2 mb-10">Products Compare</h1>
<h6 class = "text-body mb-40">There are products to compare</h6>
<div class = "table-responsive">
<table class = "table text-center table-compare">
<tbody id = "compare">
</tbody>
</table>
</div>
</div>
</div>
</div>
master_dashboard.blade.php
<!-- /// Start Load Compare Data -->
<script type = "text/javascript">
function compare() {
$.ajax({
type: "GET",
dataType: 'json',
url: "/get-compare-product/",
success:function(response){
$('#compareQty').text(response.compareQty);
const items = response.compare;
if (!items.length) {
$('.table-compare').replaceWith('<p>Nothing to compare</p>');
}
const getItemDisplayForRowKey = (item, key) => {
if (key === 'product_qty') {
const isInStock = item.product.product_qty > 0;
const className = isInStock ? 'in-stock' : 'out-stock';
return `<div class = "stock-status ${className} mb-0">${isInStock ? 'In Stock' : 'Out of stock'}</div>`;
} else if (key === 'product_thambnail') {
return `<img src = "${item.product.product_thambnail}" style = "width:300px; height:300px;">`;
} else if (key === 'selling_price') {
return `<div product_price"><h4 class = "price text-brand"> AED ${item.product.discount_price || item.product.selling_price}</h4></div>`;
} else if (key === 'short_descp') {
return `<div row_text font-xs"><p class = "font-sm text-muted">${item.product.short_descp}</p></div>`;
} else if (key === 'product_name') {
return `<div><h6><a href = "{{ url('product/details/'.$product->id.'/'.$product->product_slug) }}" class = "text-heading">${item.product.product_name}</a></h6></div>`;
}
return item.product[key];
}
const rowHeading = {
product_thambnail: 'Preview',
product_name: 'Name',
product_qty: 'Quantity',
selling_price: 'Price',
short_descp: 'Description'
};
const html = ['product_thambnail', 'product_name', 'product_qty', 'selling_price', 'short_descp'].map(rowKey => {
return `
<tr class = "pr_image">
<td class = "text-muted font-sm fw-600 font-heading">${rowHeading[rowKey]}</td>
${items.map(item => {
return `<td>${getItemDisplayForRowKey(item, rowKey)}</td>`
})}
</tr>
`
});
const actionsRow = `
<tr>
<td></td>
${items.map(item => {
return `
<td class = "row_remove"><a type = "submit" class = "text-muted" id = "${item.id}" onclick = "compareRemove(this.id)"><i class = "fi-rs-trash mr-5"></i><span>Remove</span></td>`;
})}
<tr>
`;
$('#compare').html(html + actionsRow);
}
});
}
compare();
// / End Load Compare Data -->
</script>
// Функция сравнения и удаления
function compareRemove(id){
$.ajax({
type: "GET",
dataType: 'json',
url: "/compare-remove/"+id,
success:function(data){
compare();
// Start Message
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
})
if ($.isEmptyObject(data.error)) {
Toast.fire({
type: 'success',
icon: 'success',
title: data.success,
})
}else{
Toast.fire({
type: 'error',
icon: 'error',
title: data.error,
})
}
// End Message
}
})
}
//Маршрут сведений о продукте
Route::get('/product/details/{id}/{slug}', [IndexController::class, 'ProductDetails']);
//Контроллер индекса
public function ProductDetails($id,$slug){
$product = Product::findOrFail($id);
return view('frontend.product.product_details',compact('product'));
} // End Method
Любые предложения приветствуются.
Заранее спасибо.
Структура таблицы, которую вы хотите, более сложна, чем та, которую вы сейчас визуализируете. Важно понимать, что для каждой строки вы хотите отобразить свойство каждого объекта продукта. Это говорит нам о том, что нам понадобятся вложенные циклы. Внешний цикл будет проходить по атрибутам продукта, а внутренний цикл — по каждому продукту.
Мы можем начать с массива ключей, которые будут представлять наши строки. Каждый ключ будет свойством продукта, который мы хотим отобразить в этой строке.
Если бы мы просто хотели отображать значение каждого элемента продукта по соответствующему ключу, это было бы очень просто. Однако у нас есть случаи с определенной логикой сопоставления — например, отображение selling_price
или discount_price
. Поэтому мы собираемся использовать функцию для сопоставления элемента продукта с выходными данными для ключа, инкапсулируя конкретную логику сопоставления.
Мы также должны включить объект для сопоставления ключей строк с понятным отображаемым значением.
Обратите внимание, что в приведенном примере кода я не включил классы CSS или любые другие атрибуты HTML. Это просто базовый HTML.
const response = {
compare: [
{
product: {
discount_price: null,
product_thumbnail: 'https://images.unsplash.com/photo-1570913149827-d2ac84ab3f9a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=100&q=80',
product_name: 'Product One',
product_qty: 5,
selling_price: 100,
short_descp: 'A little about Product One'
}
},
{
product: {
discount_price: 199,
product_thumbnail: 'https://images.unsplash.com/photo-1570913149827-d2ac84ab3f9a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=100&q=80',
product_name: 'Product Two',
product_qty: 0,
selling_price: 200,
short_descp: 'A little about Product Two'
}
}
]
}
$('#compareQty').text(response.compareQty);
const getItemDisplayForRowKey = (item, key) => {
if (key === 'product_qty') {
return item.product.product_qty > 0 ? 'In Stock' : 'Stock Out';
} else if (key === 'product_thumbnail') {
return `<img src = "${item.product.product_thumbnail}">`;
} else if (key === 'selling_price') {
return item.product.discount_price || item.product.selling_price;
}
return item.product[key];
}
const rowHeading = {
product_thumbnail: '',
product_name: 'Name',
product_qty: 'Quantity',
selling_price: 'Price',
short_descp: 'Description'
};
const html = ['product_thumbnail', 'product_name', 'product_qty', 'selling_price', 'short_descp'].map(rowKey => {
return `
<tr>
<td>${rowHeading[rowKey]}</td>
${response.compare.map(item => {
return `<td>${getItemDisplayForRowKey(item, rowKey)}</td>`
})}
</tr>
`
});
$('#compare').html(html);
table {
border: 1px solid black;
border-collapse: collapse;
}
tr {
border: 1px solid black;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "page-header breadcrumb-wrap">
<div class = "container">
<div class = "breadcrumb">
<a href = "index.html" rel = "nofollow"><i class = "fi-rs-home mr-5"></i>Home</a>
<span></span> Compare
</div>
</div>
</div>
<div class = "container mb-80 mt-50">
<div class = "row">
<div class = "col-xl-10 col-lg-12 m-auto">
<h1 class = "heading-2 mb-10">Products Compare</h1>
<h6 class = "text-body mb-40">There are products to compare</h6>
<div class = "table-responsive">
<table class = "table text-center table-compare">
<tbody id = "compare"></tbody>
</table>
</div>
</div>
</div>
</div>
@MuhammadYaseen: Намерение состояло в том, чтобы вы заменили то, что находится в вашем обработчике success
, кодом выше, чтобы иметь правильную структуру HTML. После этого вам нужно будет добавить свои классы CSS.
Спасибо, это работает, но я хочу добавить кнопку удаления в таблицу, которая выглядит следующим образом, где я могу разместить код; <td class = "row_remove"> <a type = "submit" class = "text-muted" id = "${value.id}" onclick = "compareRemove(this.id)"><i class = "fi- rs-trash mr-5"></i> <span>Удалить</span> </a> </td>
@MuhammadYaseen Что делает функция compareRemove
?
Спасибо за ответ. Он удаляет отдельный продукт из списка сравнения.
@MuhammadYaseen: Спасибо. Приводит ли это к совершенно новому HTTP-запросу или нам нужно повторно отображать таблицу во внешнем интерфейсе?
@MuhammadYaseen: пример удаления элемента и повторного рендеринга во внешнем интерфейсе можно найти здесь: jsfiddle.net/76484/12yebcxa
Спасибо за ваш ответ. В скрипке он работает нормально, но в моем коде, когда я нажимаю кнопку «Удалить», он не удаляет элемент, а добавляет больше элементов, потому что не может получить идентификатор продукта, необходимый для удаления. Кроме того, я обновил master_dashboard.blade.php и добавил функцию compareRemove, которую я добавил в свой пост, который вы можете найти выше.
@MuhammadYaseen: если вы повторно извлекаете свои элементы после удаления (вызывая compare
), вам не нужна эта логика, чтобы найти индекс для удаления - элемент будет удален в следующем ответе на выборку. Однако вам нужно будет переместить обработчик click
за пределы compare
, иначе он будет неоднократно применяться при вызове compare
. jsfiddle.net/76484/p3b08ejL является примером, но он не будет удалять элементы, потому что у него нет API удаления.
Спасибо за ваш ответ. Я обновил master_dashboard.blade.php, и теперь функция удаления работает нормально. Поскольку мы сопоставляем элементы, я не могу настроить таргетинг на данные конкретной ячейки таблицы, поскольку все содержится в одном элементе «td». Например, я хочу добавить class = "stock-status in-stock mb-0" для "td", содержащего текст "In Stock" и другие стили для отдельных элементов td. Как мне этого добиться?
@MuhammadYaseen: вы можете переместить рендеринг <td>
в функцию сопоставления и добавить туда логику для применения имен классов. Пример: jsfiddle.net/76484/uopxfsrg
Большое спасибо за Ваш ответ. Я получаю сообщение об ошибке «Неопределенная переменная $id», которую я передал в соответствующем блоке else if в обновленном блейд-файле master_dashboard, который выглядит следующим образом: else if (key === 'product_name') { return <div>< h6><a href = "{{ url('product/details/'.$product->id.'/'.$product->product_slug) }}" class = "text-heading">${item .product.product_name}</a></h6></div>; } и я поместил php-код в тот же файл, что и; @php $product = App\Models\Product::findOrFail($id); $id = $product->id /@endphp . Кроме того, я добавил функцию маршрута и контроллера, см.
@MuhammadYaseen: вы не можете выполнять PHP-код в JavaScript. Если вам нужен URL-адрес каждого продукта, вам нужно либо добавить его к каждому продукту в ответе сервера, чтобы он был доступен для вашего JavaScript, либо вы могли бы просто создать его на стороне клиента, используя id
и product_slug
, как я сделал здесь: jsfiddle.net/76484/yhqt90de
Спасибо за ваш ответ, и я получаю какую-то ошибку в моем коде, которая выглядит следующим образом: сравните: 1609 Uncaught TypeError: Не удается прочитать свойства неопределенного (чтение «длина»), и код выглядит следующим образом; if (!items.length) { $('.table-compare').replaceWith('<p>Нечего сравнивать</p>'); } Я не могу понять, где я ошибся.
@MuhammadYaseen: Это будет означать, что ваш объект response
не содержит свойства compare
(которое мы присваиваем переменной items
). Вам нужно будет проверить свой объект response
, чтобы увидеть, что он содержит. Код ожидает свойство compare
, значением которого является массив.
Спасибо за ваш ответ. Я проверил ответ с помощью console.info(response); сразу после успеха: функция (ответ) { и я получил результат следующим образом; 0: {id: 19, user_id: 3, product_id: 8, created_at: '2023-04-22T06:46:10.000000Z', updated_at: null, …} длина: 6, но все равно показывает ту же ошибку, и я не т видеть продукты на экране.
@MuhammadYaseen: Изменился ли ответ? Он больше не содержит свойство compare
? Я не уверен, что вы меняете ответ сервера, но если вы измените форму этого объекта, код на стороне клиента необходимо будет обновить, чтобы отразить эти изменения. Предполагая, что ответ представляет собой плоский массив объектов продукта, код на стороне клиента должен выглядеть так: jsfiddle.net/76484/rvLe7h9q
Спасибо за ответ. Нет, ответ не изменился, и я проверил код следующим образом; успех: функция (ответ) { const items = response.compare; console.info(элементы); if (!items.length) { $('.table-compare').replaceWith('<p>Нечего сравнивать</p>'); } и теперь я получаю значение undefined.
@MuhammadYaseen Каков ответ? Пожалуйста, добавьте его в свой пост.
Спасибо за ваш ответ. Эта проблема решена, но теперь мне нужно перебрать все строки таблицы следующего элемента, который является <td>${rowHeading[rowKey]}</td>, и добавить определенные классы к каждому из значений rowHeading. Для значения «Имя» ключа product_name добавьте class = "pr_title" для достижения следующего <tr class = "pr_title"></tr> и аналогично для значения «Цена» ключа Selling_price добавьте class = "pr_title" для достижения следующего <tr class = "pr_price"></tr>и т. д. для других строк таблицы соответственно.
Давайте продолжим обсуждение в чате.
Большое спасибо за ваш отличный ответ. Могу ли я применить его к моему существующему коду, или я должен пойти в соответствии с вашим кодом.