Thymeleaf and spring - pagination for table? - spring-boot

I am developing one spring-boot application. I have to print Hashmap resultset as a table. For that I have created table using thymeleaf. The table has sometimes over 100k records. I want pagination for this table every 10 or 50 records.
My html using thymeleaf code snippet:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:dt="http://www.thymeleaf.org/dandelion/datatables">
<head lang="en">
.
.
<div id="myDivTable">
<table class="table table-bordered" id="bomTable" id="bomTable"
dt:table="true" dt:displaylength="10">
<span th:each="row, iter : ${result}" pages:paginate="5">
<tr th:classappend="${iter.first} ? header-style">
<span th:each="cell : ${row.value}">
<td th:classappend="${#strings.contains(cell,'difference')}?set-difference-bg-color" >
<div th:switch="${cell}">
<div th:case="'Only in WC'" >
<span class="set-green-text-bold" th:text="${cell}">
</span>
</div>
<div th:case="'New in XLSX'" >
<span class="set-red-text-bold" th:text="${cell}">
</span>
</div>
<div th:case="'No'" >
<span class="set-red-text-bold" th:text="${cell}">
</span>
</div>
<div th:case="'Yes'" >
<span class="set-green-text-bold" th:text="${cell}">
</span>
</div>
<div th:case="*" >
<div th:if="${#strings.contains(cell,'difference')}">
<span
th:text="${#strings.substring(cell,0,#strings.indexOf(cell,'difference'))}">
</span>
</div>
<div th:unless="${#strings.contains(cell,'difference')}">
<span th:text="${cell}"></span>
</div>
</div>
</div>
</td>
</span>
</tr>
</span>
</table>
</div>
.
.
Recently it is printing all the records on one single page. I am checking for 120 records. How I can split the records 10 or 50 on each page. I am using Thymeleaf.
I have tried to use dandelion datatables, I have added dependencies in pom.xml, create dandelinConfig class etc but still it is not reflecting in result.

You can do it with using Dandelion Datatables.
Sample usage like this :
<dependency>
<groupId>com.github.dandelion</groupId>
<artifactId>datatables-thymeleaf</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.github.dandelion</groupId>
<artifactId>datatables-spring3</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.github.dandelion</groupId>
<artifactId>dandelion-thymeleaf</artifactId>
<version>1.1.1</version>
</dependency>
And Configuration class is :
#Configuration
public class DandelionConfig {
#Bean
public DandelionDialect dandelionDialect() {
return new DandelionDialect();
}
#Bean
public DataTablesDialect dataTablesDialect(){
return new DataTablesDialect();
}
#Bean
public Filter dandelionFilter() {
return new DandelionFilter();
}
#Bean
public ServletRegistrationBean dandelionServletRegistrationBean() {
return new ServletRegistrationBean(new DandelionServlet(), "/dandelion-assets/*");
}
}
The you should add dandelion folder under resources folder : /resources/dandelion/. And then create /resources/dandelion/sample.json file like below :
{
"bundle" : "custom",
"assets": [
{
"name": "bootstrap4-datatables-css",
"type": "css",
"locations": {
"classpath": "static/css/dataTables.bootstrap4.min.css"
}
},
{
"name": "jquery-datatables-js",
"type": "js",
"locations": {
"classpath": "static/js/jquery.dataTables.min.js"
}
},
{
"name": "bootstrap4-datatables-js",
"type": "js",
"locations": {
"classpath": "static/js/dataTables.bootstrap4.min.js"
}
},
}
]
}
and create /resources/dandelion/dandelion.properties file :
components.standalone=ddl-dt
bundle.includes=custom
add aplication properties file components.standalone = ddl-dt
.Finally example html file :
<html xmlns:th="http://www.thymeleaf.org"
xmlns:dt="http://www.thymeleaf.org/dandelion/datatables"
>
<table id="paging-simple" dt:table="true" dt:pagingType="simple" class="display">
<thead>
<tr>
<th>Id</th>
<th>Firstname</th>
<th>Lastname</th>
<th>City</th>
<th>Mail</th>
</tr>
</thead>
<tbody>
<tr th:each="person : ${persons}">
<td th:text="${person?.id}">1</td>
<td th:text="${person?.firstName}">John</td>
<td th:text="${person?.lastName}">Doe</td>
<td th:text="${person?.address?.town?.name}">Nobody knows!</td>
<td th:text="${person?.mail}">john#doe.com</td>
</tr>
</tbody>
</table>
.Finally if you want to add pagination your project you will do it ajax request.Detail is Dandelion Datatables Ajax

im using springboot, java, thymeleaf, foundation(js) and mysql, idontknow about dandelion, but with spring Pageable i can do this
public String listadoProductos(Pageable pageable, Model model) {
if(pageable.getPageSize() > PAGE_SIZE_INITIAL) {
pageable = new PageRequest(0,PAGE_SIZE_INITIAL);
}
Page<Productos> productos = productosRepository.findByEnabled(true, pageable);//trae todos los productos habilitados
model.addAttribute("productos", productos);
modelPaginacion(model, productos, pageable.getPageNumber());
return tiendaFolder+"listaProductos";}
and with thyeleaf and foundation do this:
<div class="row">
<ul class="paginacion text-center">
<li class="previous" th:if="${previo}">
<a th:href="#{/tienda/productos/admin?page={pa}&size={ps}(pa=${paginaActual-1},ps=${size})}"></a>
</li>
<li class="previa" th:if="${previo}">
<a th:href="#{/tienda/productos/admin?page={pa}&size={ps}(pa=${paginaActual-1},ps=${size})}" th:text="${paginaActual-1}"></a>
</li>
<li class="actual" th:text="${paginaActual}">
</li>
<li class="siguiente" th:if="${siguiente}">
<a th:href="#{/tienda/productos/admin?page={pa}&size={ps}(pa=${paginaActual+1},ps=${size})}" th:text="${paginaActual+1}"></a>
</li>
<li class="next" th:if="${siguiente}">
<a th:href="#{/tienda/productos/admin?page={pa}&size={ps}(pa=${paginaActual+1},ps=${size})}"></a>
</li>
</ul>
</div>
is only the block o number of pages

Related

Datatable view is not in style/standard format

I am trying to figure out what I've missed during my coding on my project. My problem is my datatable format/style is not what it seems to look like from standard format. I'm using ASP.net MVC.
This is the output: Page numbers, search box is not in style
Page numbers, search box is not in style
Here is my code:
<div class="row">
<div class="col-sm-20c">
<div class="panel-body">
<table id="tbl-transaction" class="table table-bordered" cellspacing="0" width="100%" align="center">
<thead>
<tr>
<th>Transaction No</th>
<th>Purpose of Visit</th>
<th>Name of Host</th>
<th>Transacted By</th>
<th>Details</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
#section Scripts
{
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.dataTables.min.js"></script>
<script>
getall();
function getall()
{
$('#tbl-transaction').dataTable().fnDestroy();
$('#tbl-transaction').DataTable({
"ajax": {
"url": '/FSEWeb/Admin/GetAllTransactions',
"type": "get",
"datatype" : "JSON"
},
"columns" :
[
{ data :"TransactionNumber"},
{ data: "PurposeOfVisit" },
{ data: "NameOfHostFromST" },
{ data: "TransactedBy" },
{
data: null, "render" : function(data,type,row)
{
return '<button class= "btn btn-success" onclick = "get_details(' + data.id + ',' + data.TransactionNumber + ')"> Details </button>';
}
}
]
})
}
This table format is what I want to look like.
Desired output with styles
You have not incorporated JQuery Datatbles style sheet i.e.
<!-- Data table -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.10/css/dataTables.bootstrap.min.css " />
Incorporate it at layout level or page level.

Cannot find parent element in DOM tree containing attribute: [wire:id]

I am laravel developer and developing a real time chat room using liveware , i am trying to open chat when i click to user but unfortunatly i am getting error https://flareapp.io/share/OmVDe437#F47 please help me how can resolved that ? thank u.
I am also getting error in console.
app\Http\Livewire\Messaging.php
public $selectedConservation;
public function mount(){
$this->selectedConservation = Conservation::query()
->where('sender_id',Auth::user()->id)
->orwhere('reciever_id',Auth::user()->id)
->first();
}
public function viewMessages($conservationsId){
$this->selectedConservation =
Conservation::findorFail($conservationsId);
}
public function render()
{
$conservation = Conservation::query()
->where('sender_id',Auth::user()->id)
->orwhere('reciever_id',Auth::user()->id)
->get();
return view('livewire.messaging',[
'conservation' => $conservation,
]);
}
resources\views\livewire\messaging.blade.php
#foreach ($conservation as $conservations)
<a href="#" wire:click.prevent="viewMessages({{ $conservations->id}} )">
<div class="user-card rounded bg-dark bg-opacity-10 mb-1">
<div class="mx-2">
<div class="d-flex pt-3">
<img class="rounded-circle" width="48px" height="48px" src="{{Config('wfh.file').$conservations->reciever->avator}}" alt="">
<div class="notification-text ms-3 w-100">
<span class="username fw-bold">{{$conservations->reciever->full_name}}</span>
<span class="float-end small"></span>
<p class="mt-1 text-muted">You: </p>
</div>
</div>
</div>
</div>
</a>
#endforeach
Check out the documentation on Dom Diffing Issues. It looks like you need to add a wire:key="{{ $conversations->id }}" attribute into your a tag so that Livewire can track changes to the list of conversations.

Spring Boot + Thymeleaf: combine filtering and pagination for list

Good evening all,
I'm learning Thymeleaf and web applications in general right now, and for starters, I'm trying to implement a web service with a page where you can view all registered users and filter them.
Since I want some pagination, I have two forms on this page:
a group of buttons linking to the first, previous, next, and last page
a form with various options for filtering, e.g. "username contains" or "min / max age"
My controller looks like this:
#RequestMapping("/users/all")
String showSearchPage(#RequestParam(value="page", required=false, defaultValue = "0") int page,
#CurrentSecurityContext(expression="authentication?.name") String username,
Model model) {
Page<User> userPage = userService.filterUsers(username, "", 0, 100, PageRequest.of(page, 10));
model.addAttribute("userPage", userPage);
model.addAttribute("pageNr", page);
return "users.html";
}
As you can see, I only implemented the buttons yet and always filter for some default values. (The username parameter makes sure that the currently logged in user isn't finding themself in the list.) My button form looks like that:
<form class="button" th:action="#{/users/all}" method="POST">
<button th:disabled="${pageNr == 0}" type="submit"
class="btn btn-primary"
name="page" th:value="0"><<</button>
<button th:disabled="${pageNr == 0}" type="submit"
class="btn btn-primary"
name="page" th:value="${pageNr - 1}"><</button>
<button th:disabled="${pageNr == userPage.getTotalPages - 1}" type="submit"
class="btn btn-primary"
name="page" th:value="${pageNr + 1}">></button>
<button th:disabled="${pageNr == userPage.getTotalPages - 1}" type="submit"
class="btn btn-primary"
name="page" th:value="${userPage.getTotalPages - 1}">>></button>
</form>
So I'm using the request parameter page to only show the requested page.
Now that I'm about to implement the filtering, my first approach would be adding the form to my HTML, and adding some #ModelAttribute FilterForm filterForm to my controller to be able to get the submitted filter values and use them to retrieve the filtered user list. However, when thinking about it, I found the problem that both forms would only submit their own content, and the controller would only get one of both. Therefore, after filtering users, I would inadvertedly revert back to the full user list when changing pages.
What would be the best approach here to make sure that both functions, filtering and pagination, work together properly?
Thanks in advance!
I'd go with HTTP GET method instead of POST. Why so? Reading users is an idempotent and safe operation. The applied filter and page number can be easily bookmarked in that case.
For filters, you can just add more params. Nothing bad about that.
Make it a bit more RESTful. "/users/all" is unnecessary. "/users" should be enough.
#GetMapping("/users")
String showSearchPage(#RequestParam(value="page", required=false, defaultValue = "0") int page,
#RequestParam("minAge") Optional<Integer> minAge,
#RequestParam("maxAge") Optional<Integer> maxAge,
#CurrentSecurityContext(expression="authentication?.name") String username,
Model model) {
// Apply filters too...
Page<User> userPage = userService.filterUsers(username, "", 0, 100, PageRequest.of(page, 10));
model.addAttribute("userPage", userPage);
model.addAttribute("pageNr", page);
model.addAttribute("nextPage", getPageWithFilterUrl(page + 1, minAge, maxAge));
model.addAttribute("previousPage", getPageWithFilterUrl(page - 1, minAge, maxAge));
return "users.html";
}
To preserve filter while moving back and forth:
private String getPageWithFilterUrl(int page, Optional<Integer> minAge, Optional<Integer> maxAge) {
String defaultNextPageUrl = "/users?page=" + page;
String withMinAge = minAge.map(ma -> defaultNextPageUrl + "&minAge=" + ma).orElse(defaultNextPageUrl);
String withMaxAge = maxAge.map(ma -> withMinAge + "&maxAge=" + ma).orElse(withMinAge);
return withMaxAge;
}
I think the answer is not given here yet. I have the same problem now. I am trying in my project with redirectAttributes.addFlashAttribute("searchProductItemDTO", searchProductItemDTO);
But the problem comes when clicking on the Next/Previous buttons - clicking them does not take into account the search criteria.
Here is my total solution:
1) Pay attention here to the JpaSpecificationExecutor<ItemEntity>
#Repository
public interface AllItemsRepository extends
PagingAndSortingRepository<ItemEntity, Long>, JpaSpecificationExecutor<ItemEntity>{
}
2) Pay attention here to the CriteriaBuilder
public class ProductItemSpecification implements Specification<ItemEntity> {
private final SearchProductItemDTO searchProductItemDTO;
private final String type;
public ProductItemSpecification(SearchProductItemDTO searchProductItemDTO, String type) {
this.searchProductItemDTO = searchProductItemDTO;
this.type = type;
}
#Override
public Predicate toPredicate(Root<ItemEntity> root,
CriteriaQuery<?> query,
CriteriaBuilder cb) {
Predicate predicate = cb.conjunction();
predicate.getExpressions().add(cb.equal(root.get("type"), type));
if (searchProductItemDTO.getModel() != null && !searchProductItemDTO.getModel().isBlank()) {
Path<Object> model = root.get("model");
predicate.getExpressions().add(
//!!!!! when we have two relationally connected tables
// cb.and(cb.equal(root.join("model").get("name"), searchProductItemDTO.getModel()));
//when all fields are from the same table ItemEntity:::: the like works case insensitive
cb.and(cb.like(root.get("model").as(String.class), "%" + searchProductItemDTO.getModel() + "%"))
);
}
if (searchProductItemDTO.getMinPrice() != null) {
predicate.getExpressions().add(
cb.and(cb.greaterThanOrEqualTo(root.get("sellingPrice"),
searchProductItemDTO.getMinPrice()))
);
}
if (searchProductItemDTO.getMaxPrice() != null) {
predicate.getExpressions().add(
cb.and(cb.lessThanOrEqualTo(root.get("sellingPrice"),
searchProductItemDTO.getMaxPrice()))
);
}
return predicate;
}
}
3) Pay attention here to the this.allItemsRepository.findAll default usage
//Complicated use
public Page<ComputerViewGeneralModel> getAllComputersPageableAndSearched(
Pageable pageable, SearchProductItemDTO searchProductItemDTO, String type) {
Page<ComputerViewGeneralModel> allComputers = this.allItemsRepository
.findAll(new ProductItemSpecification(searchProductItemDTO, type), pageable)
.map(comp -> this.structMapper
.computerEntityToComputerSalesViewGeneralModel((ComputerEntity) comp));
return allComputers;
}
4) Pay attention here to the redirectAttributes.addFlashAttribute
#Controller
#RequestMapping("/items/all")
public class ViewItemsController {
private final ComputerService computerService;
#GetMapping("/computer")
public String viewAllComputers(Model model,
#Valid SearchProductItemDTO searchProductItemDTO,
#PageableDefault(page = 0,
size = 3,
sort = "sellingPrice",
direction = Sort.Direction.ASC) Pageable pageable,
RedirectAttributes redirectAttributes) {
if (!model.containsAttribute("searchProductItemDTO")) {
model.addAttribute("searchProductItemDTO", searchProductItemDTO);
}
Page<ComputerViewGeneralModel> computers = this.computerService
.getAllComputersPageableAndSearched(pageable, searchProductItemDTO, "computer");
model.addAttribute("computers", computers);
redirectAttributes.addFlashAttribute("searchProductItemDTO", searchProductItemDTO);
return "/viewItems/all-computers";
}
5) Pay attention here to all the search params that we add in the html file, in the 4 sections where pagination navigation
<main>
<div class="container-fluid">
<div class="container">
<h2 class="text-center text-white">Search for offers</h2>
<form
th:method="GET"
th:action="#{/items/all/computer}"
th:object="${searchProductItemDTO}"
class="form-inline"
style="justify-content: center; margin-top: 50px;"
>
<div style="position: relative">
<input
th:field="*{model}"
th:errorclass="is-invalid"
class="form-control mr-sm-2"
style="width: 280px;"
type="search"
placeholder="Model name case Insensitive..."
aria-label="Search"
id="model"
/>
<input
th:field="*{minPrice}"
th:errorclass="is-invalid"
class="form-control mr-sm-2"
style="width: 280px;"
type="search"
placeholder="Min price..."
aria-label="Search"
id="minPrice"
/>
<input
th:field="*{maxPrice}"
th:errorclass="is-invalid"
class="form-control mr-sm-2"
style="width: 280px;"
type="search"
placeholder="Max price..."
aria-label="Search"
id="maxPrice"
/>
</div>
<button class="btn btn-outline-info my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
<h2 class="text-center text-white mt-5 greybg" th:text="#{view_all_computers}">.........All
Computers.......</h2>
<div class="offers row mx-auto d-flex flex-row justify-content-center .row-cols-auto">
<div
th:each="c : ${computers}" th:object="${c}"
class="offer card col-sm-2 col-md-3 col-lg-3 m-2 p-0">
<div class="card-img-top-wrapper" style="height: 20rem">
<img
class="card-img-top"
alt="Computer image"
th:src="*{photoUrl}">
</div>
<div class="card-body pb-1">
<h5 class="card-title"
th:text="' Model: ' + *{model}">
Model name</h5>
</div>
<ul class="offer-details list-group list-group-flush">
<li class="list-group-item">
<div class="card-text"><span th:text="'* ' + *{processor}">Processor</span></div>
<div class="card-text"><span th:text="'* ' + *{videoCard}">Video card</span></div>
<div class="card-text"><span th:text="'* ' + *{ram}">Ram</span></div>
<div class="card-text"><span th:text="'* ' + *{disk}">Disk</span></div>
<div th:if="*{!ssd.isBlank()}" class="card-text"><span th:text="'* ' + *{ssd}">SSD</span></div>
<div th:if="*{!moreInfo.isBlank()}" class="card-text"><span th:text="'* ' + *{moreInfo}">More info</span>
</div>
<div class="card-text"><span th:text="'We sell at: ' + *{sellingPrice} + ' лв'"
style="font-weight: bold">Selling price</span></div>
</li>
</ul>
<div class="card-body">
<div class="row">
<a class="btn btn-link"
th:href="#{/items/all/computer/details/{id} (id=*{itemId})}">Details</a>
<th:block sec:authorize="hasRole('ADMIN') || hasRole('EMPLOYEE_PURCHASES')">
<a class="btn btn-link alert-danger"
th:href="#{/pages/purchases/computers/{id}/edit (id=*{itemId})}">Update</a>
<form th:action="#{/pages/purchases/computers/delete/{id} (id=*{itemId})}"
th:method="delete">
<input type="submit" class="btn btn-link alert-danger" value="Delete"></input>
</form>
</th:block>
</div>
</div>
</div>
</div>
<div class="container-fluid row justify-content-center">
<nav>
<ul class="pagination">
<li class="page-item" th:classappend="${computers.isFirst()} ? 'disabled' : ''">
<a th:unless="${computers.isFirst()}"
class="page-link"
th:href="#{/items/all/computer(size=${computers.getSize()},page=0,model=${searchProductItemDTO.getModel()}, minPrice=${searchProductItemDTO.getMinPrice()},maxPrice=${searchProductItemDTO.getMaxPrice()})}">First</a>
</li>
</ul>
</nav>
<nav>
<ul class="pagination">
<li class="page-item" th:classappend="${computers.hasPrevious() ? '' : 'disabled'}">
<a th:if="${computers.hasPrevious()}"
class="page-link"
th:href="#{/items/all/computer(size=${computers.getSize()},page=${computers.getNumber() - 1},model=${searchProductItemDTO.getModel()}, minPrice=${searchProductItemDTO.getMinPrice()},maxPrice=${searchProductItemDTO.getMaxPrice()})}">Previous</a>
</li>
</ul>
</nav>
<nav>
<ul class="pagination">
<li class="page-item" th:classappend="${computers.hasNext() ? '' : 'disabled'}">
<a th:if="${computers.hasNext()}"
class="page-link"
th:href="#{/items/all/computer(size=${computers.getSize()},page=${computers.getNumber() + 1},model=${searchProductItemDTO.getModel()}, minPrice=${searchProductItemDTO.getMinPrice()},maxPrice=${searchProductItemDTO.getMaxPrice()})}">Next</a>
</li>
</ul>
</nav>
<nav>
<ul class="pagination">
<li class="page-item" th:classappend="${computers.isLast()} ? 'disabled' : ''">
<a th:unless="${computers.isLast()}"
class="page-link"
th:href="#{/items/all/computer(size=${computers.getSize()},page=${computers.getTotalPages()-1},model=${searchProductItemDTO.getModel()},minPrice=${searchProductItemDTO.getMinPrice()},maxPrice=${searchProductItemDTO.getMaxPrice()})}">Last</a>
</li>
</ul>
</nav>`enter code here`
</div>
</div>
</main>

KnockoutJS elements not rendered once loaded via Jquery Ajax function

I have loaded a sidebar over ajax however this html uses knockoutJS to render completely. I am wondering how to execute the KnockoutJs portions of this code.
The content below is loaded via jQuery ajax function and contains a number of knockout elements as well as some X Magento Init type scripts:
<div class=\"block filter\" id=\"layered-filter-block\" data-mage-init='{\"collapsible\":{\"openedState\": \"active\", \"collapsible\": true, \"active\": false, \"collateral\": { \"openedState\": \"filter-active\", \"element\": \"body\" } }}'>
<div class=\"block-title filter-title\" data-count=\"0\">
<strong data-role=\"title\">Shop By<\/strong>
<\/div>
<div class=\"block-content filter-content\">
<strong role=\"heading\" aria-level=\"2\" class=\"block-subtitle filter-subtitle\">Shopping Options<\/strong>
<div class=\"filter-options\" id=\"narrow-by-list\" data-role=\"content\" data-mage-init='{\"accordion\":{\"openedState\": \"active\", \"collapsible\": true, \"active\": [0,1,2], \"multipleCollapsible\": true}}'>
<div data-role=\"collapsible\" class=\"filter-options-item\">
<div data-role=\"title\" class=\"filter-options-title\">Category<\/div>
<div data-role=\"content\" class=\"filter-options-content\">\n<ol class=\"items\">
<li class=\"item\">
<a href=\"http:\/\/www.domain.com\/catalogsearch\/result\/index\/?ajax=1&cat=143&q=ice+machine\">Front of House
<span class=\"count\">2<span class=\"filter-count-label\">items<\/span><\/span><\/a>
<\/li>
<li class=\"item\">
<a href=\"http:\/\/www.domain.com\/catalogsearch\/result\/index\/?ajax=1&cat=182&q=ice+machine\">Bar Supplies
<span class=\"count\">4<span class=\"filter-count-label\">items<\/span><\/span><\/a>
<\/li>
<li class=\"item\">
<a href=\"http:\/\/www.domain.com\/catalogsearch\/result\/index\/?ajax=1&cat=257&q=ice+machine\">Catering Equipment<span class=\"count\">111<span class=\"filter-count-label\">\n
items <\/span><\/span>\n
<\/a>\n <\/li>\n
<li class=\"item\">\n
<a href=\"http:\/\/www.domain.com\/catalogsearch\/result\/index\/?ajax=1&cat=342&q=ice+machine\">\n
Warewashing <span class=\"count\">\n
3 <span class=\"filter-count-label\">\n
items <\/span><\/span>\n
<\/a>\n <\/li>\n <li class=\"item\">\n
<a href=\"http:\/\/www.domain.com\/catalogsearch\/result\/index\/?ajax=1&cat=521&q=ice+machine\">\n
Catering Equipment Offers <span class=\"count\">\n 1
<span class=\"filter-count-label\">\n item <\/span><\/span>\n
<\/a>\n <\/li>\
<\/ol>
<\/div>\n
<\/div>\n
<div data-role=\"collapsible\" class=\"filter-options-item\">
<div data-role=\"title\" class=\"filter-options-title\">Brand<\/div>\n
<div data-role=\"content\" class=\"filter-options-content\">
<div data-bind=\"scope: 'brandFilter'\">
<!-- ko template: getTemplate() --> <!-- \/ko -->
<\/div>
<script type=\"text\/x-magento-init\">
{\"*\" : {\"Magento_Ui\/js\/core\/app\": {\"components\": {\"brandFilter\": {\"component\":\"Smile_ElasticsuiteCatalog\\\/js\\\/attribute-filter\",\"maxSize\":10,\"displayProductCount\":true,\"hasMoreItems\":true,\"ajaxLoadUrl\":\"http:\\\/\\\/www.domain.com\\\/catalog\\\/navigation_filter\\\/ajax\\\/?ajax=1&filterName=brand&q=ice+machine\",\"items\":[{\"label\":\"Scotsman\",\"count\":41,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Scotsman&q=ice+machine\",\"is_selected\":false},{\"label\":\"Hoshizaki\",\"count\":15,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Hoshizaki&q=ice+machine\",\"is_selected\":false},{\"label\":\"Ice-o-matic\",\"count\":12,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Ice-o-matic&q=ice+machine\",\"is_selected\":false},{\"label\":\"Blue Ice\",\"count\":7,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Blue+Ice&q=ice+machine\",\"is_selected\":false},{\"label\":\"Graupel\",\"count\":7,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Graupel&q=ice+machine\",\"is_selected\":false},{\"label\":\"Nemox\",\"count\":7,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Nemox&q=ice+machine\",\"is_selected\":false},{\"label\":\"Manitowoc\",\"count\":6,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Manitowoc&q=ice+machine\",\"is_selected\":false},{\"label\":\"Polar Refrigeration\",\"count\":5,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Polar+Refrigeration&q=ice+machine\",\"is_selected\":false},{\"label\":\"Longo & Co\",\"count\":4,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Longo+%26+Co&q=ice+machine\",\"is_selected\":false},{\"label\":\"Beaumont\",\"count\":3,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&brand=Beaumont&q=ice+machine\",\"is_selected\":false}]}}}}}\n<\/script>\n\n<\/div>\n <\/div>\n <div data-role=\"collapsible\" class=\"filter-options-item\">\n <div data-role=\"title\" class=\"filter-options-title\">Power<\/div>\n <div data-role=\"content\" class=\"filter-options-content\"><div data-bind=\"scope: 'power_ddFilter'\">\n <!-- ko template: getTemplate() --> <!-- \/ko -->\n<\/div>\n\n<script type=\"text\/x-magento-init\">\n {\"*\" : {\"Magento_Ui\/js\/core\/app\": {\"components\": {\"power_ddFilter\": {\"component\":\"Smile_ElasticsuiteCatalog\\\/js\\\/attribute-filter\",\"maxSize\":10,\"displayProductCount\":true,\"hasMoreItems\":false,\"ajaxLoadUrl\":\"http:\\\/\\\/www.domain.com\\\/catalog\\\/navigation_filter\\\/ajax\\\/?ajax=1&filterName=power_dd&q=ice+machine\",\"items\":[{\"label\":\"13 Amp (Plug)\",\"count\":111,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&power_dd=13+Amp+%28Plug%29&q=ice+machine\",\"is_selected\":false},{\"label\":\"1 Phase (Hard Wired)\",\"count\":2,\"url\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&power_dd=1+Phase+%28Hard+Wired%29&q=ice+machine\",\"is_selected\":false}]}}}}}\n<\/script>\n\n<\/div>\n <\/div>\n <div data-role=\"collapsible\" class=\"filter-options-item\">\n <div data-role=\"title\" class=\"filter-options-title\">Price<\/div>\n <div data-role=\"content\" class=\"filter-options-content\"><div class=\"smile-es-range-slider\" data-role=\"range-price-slider-price\">\n <div data-role=\"from-label\"><\/div>\n <div data-role=\"to-label\"><\/div>\n <div data-role=\"slider-bar\"><\/div>\n <div class=\"actions-toolbar\">\n <div data-role=\"message-box\"><\/div>\n <div class=\"actions-primary\">\n <a class=\"action primary small\" data-role=\"apply-range\">\n <span>OK<\/span>\n <\/a>\n <\/div>\n <\/div>\n<\/div>\n\n<script type=\"text\/x-magento-init\">\n { \"[data-role=range-price-slider-price]\" : { \"rangeSlider\" : {\"minValue\":1,\"maxValue\":6091,\"currentValue\":{\"from\":1,\"to\":6091},\"fieldFormat\":{\"pattern\":\"\\u00a3%s\",\"precision\":2,\"requiredPrecision\":2,\"decimalSymbol\":\".\",\"groupSymbol\":\",\",\"groupLength\":3,\"integerRequired\":false},\"intervals\":[{\"value\":1,\"count\":1},{\"value\":2,\"count\":1},{\"value\":3,\"count\":1},{\"value\":40,\"count\":1},{\"value\":60,\"count\":1},{\"value\":64,\"count\":1},{\"value\":150,\"count\":1},{\"value\":179,\"count\":1},{\"value\":190,\"count\":1},{\"value\":242,\"count\":1},{\"value\":291,\"count\":1},{\"value\":325,\"count\":1},{\"value\":355,\"count\":2},{\"value\":395,\"count\":1},{\"value\":465,\"count\":1},{\"value\":472,\"count\":1},{\"value\":515,\"count\":1},{\"value\":520,\"count\":1},{\"value\":535,\"count\":1},{\"value\":555,\"count\":1},{\"value\":577,\"count\":1},{\"value\":585,\"count\":1},{\"value\":599,\"count\":1},{\"value\":605,\"count\":2},{\"value\":615,\"count\":1},{\"value\":640,\"count\":1},{\"value\":658,\"count\":1},{\"value\":685,\"count\":1},{\"value\":705,\"count\":1},{\"value\":730,\"count\":1},{\"value\":745,\"count\":2},{\"value\":785,\"count\":1},{\"value\":805,\"count\":1},{\"value\":830,\"count\":1},{\"value\":895,\"count\":2},{\"value\":925,\"count\":1},{\"value\":965,\"count\":1},{\"value\":970,\"count\":1},{\"value\":990,\"count\":2},{\"value\":1030,\"count\":1},{\"value\":1065,\"count\":1},{\"value\":1080,\"count\":1},{\"value\":1085,\"count\":1},{\"value\":1095,\"count\":1},{\"value\":1105,\"count\":1},{\"value\":1130,\"count\":1},{\"value\":1155,\"count\":1},{\"value\":1225,\"count\":1},{\"value\":1235,\"count\":1},{\"value\":1240,\"count\":1},{\"value\":1259,\"count\":1},{\"value\":1310,\"count\":1},{\"value\":1360,\"count\":1},{\"value\":1365,\"count\":1},{\"value\":1450,\"count\":1},{\"value\":1485,\"count\":1},{\"value\":1495,\"count\":1},{\"value\":1510,\"count\":1},{\"value\":1580,\"count\":2},{\"value\":1605,\"count\":2},{\"value\":1685,\"count\":1},{\"value\":1710,\"count\":1},{\"value\":1779,\"count\":1},{\"value\":1785,\"count\":1},{\"value\":1865,\"count\":1},{\"value\":1870,\"count\":1},{\"value\":1885,\"count\":1},{\"value\":1890,\"count\":1},{\"value\":1970,\"count\":1},{\"value\":1995,\"count\":1},{\"value\":2000,\"count\":1},{\"value\":2050,\"count\":1},{\"value\":2130,\"count\":1},{\"value\":2199,\"count\":1},{\"value\":2220,\"count\":1},{\"value\":2345,\"count\":1},{\"value\":2350,\"count\":1},{\"value\":2360,\"count\":1},{\"value\":2405,\"count\":1},{\"value\":2415,\"count\":1},{\"value\":2445,\"count\":1},{\"value\":2450,\"count\":2},{\"value\":2480,\"count\":1},{\"value\":2500,\"count\":1},{\"value\":2530,\"count\":1},{\"value\":2565,\"count\":1},{\"value\":2570,\"count\":1},{\"value\":2595,\"count\":1},{\"value\":2695,\"count\":1},{\"value\":2730,\"count\":1},{\"value\":2825,\"count\":1},{\"value\":2850,\"count\":1},{\"value\":2950,\"count\":1},{\"value\":2995,\"count\":1},{\"value\":3010,\"count\":1},{\"value\":3025,\"count\":1},{\"value\":3145,\"count\":1},{\"value\":3205,\"count\":1},{\"value\":3295,\"count\":1},{\"value\":3300,\"count\":1},{\"value\":3485,\"count\":1},{\"value\":3495,\"count\":1},{\"value\":3580,\"count\":1},{\"value\":4015,\"count\":1},{\"value\":4075,\"count\":1},{\"value\":4305,\"count\":1},{\"value\":4310,\"count\":1},{\"value\":4595,\"count\":1},{\"value\":4620,\"count\":1},{\"value\":5250,\"count\":1},{\"value\":5355,\"count\":1},{\"value\":6090,\"count\":1}],\"urlTemplate\":\"http:\\\/\\\/www.domain.com\\\/catalogsearch\\\/result\\\/index\\\/?ajax=1&price=<%- from %>-<%- to %>&q=ice+machine\",\"messageTemplates\":{\"displayCount\":\"<%- count %> products\",\"displayEmpty\":\"No products in the selected range.\"},\"rate\":1}
} }
<\/script>
<\/div>
<\/div>
<\/div>
<\/div>
<\/div>
These are then added to a block on my page via html jQuery method:
$(sidebarBlock).html(this.filters);
Looking at the DOM I cannot actually see the scripts however they are there in response when reviewing with console.log(). Similarly the below shows the scripts are present:
$(sidebar).find("script").each(function() {
console.log("found a script");
}
I have tried to use .trigger('contentUpdated'); like below:
document.getElementById("layered-filter-block").innerHTML = this.filters;
$(sidebarBlock).trigger('contentUpdated');
and:
$(sidebarBlock).html(this.filters);
$(sidebarBlock).trigger('contentUpdated');
and by reapplying bindings for knockout:
ko.cleanNode($('#layered-filter-block'));
ko.applyBindings($('#layered-filter-block'));
The above throws an error about bindings already being applied however but I have used cleanNode before to unbind however error persists.
This fixed issue for me:
$(sidebarBlock).applyBindings();
https://codeblog.experius.nl/magento-2-uicomponent-reinit-ajax-reload/

using $this in view file codeIgniter

im a newbie in CI, i have some question
i have controller like below
public function show_admin()
{
$data['data_admin'] = $this->M_Admin->get_admin();
$data['page'] = 'show_admin';
$this->load->view('admin/template',$data);
}
and then i have template in my view folder, like below
<body>
<div id="wrapper">
<div id="header">
<?php
$data['session'] = $this->session->all_userdata();
$this->load->view('admin/header',$data);?>
<div id="content">
<?php
$this->load->view('admin/'.$page);?>
</div>
<div id="footer">
<?php $this->load->view('admin/footer');?>
</div>
</div>
</body>
and the show_admin (view file) like below
<div id="isi_content">
<span><img src="<?php echo base_url();?>assets/admin/images/add.png">Tambah</span>
<table class="table table-hover table-bordered">
<tr>
<th>No</th>
<th>Nama</th>
<th>Username</th>
<th>Login Terakhir</th>
<th>Aksi</th>
</tr>
<?php
$no=1;
foreach($data_admin as $admin){
$id = $admin['id_admin'];
$url = site_url('admin/C_Admin/c_delete_admin');
echo
'<tr>
<td>'.$no.'</td>
<td>'.$admin['nama_admin'].'</td>
<td>'.$admin['username'].'</td>
<td>'.$admin['tgl_last_visit'].'</td>
<td class=aksi><a href='.site_url('admin/C_Admin/c_edit_admin/'.$admin['id_admin'].'').'><img src='.base_url().'assets/admin/images/edit.png></a>
<img src='.base_url().'assets/admin/images/delete.png></td>
</tr>';
$no++;
}
?>
</table>
</div>
and that codes run nicely,
is that normal in codeIgniter use $this in view file??
im confuse about this..
thanks for your answer...
No, you should not use that session variable nor load any views on another view. This all should be done in the Controller. What you can do is break your code in pieces, like the header in its one view file and the footer in another view file, then you can load them in your controller like so:
public function show_admin()
{
$data['data_admin'] = $this->M_Admin->get_admin();
$data['page'] = 'show_admin';
$head_data['session'] = $this->session->all_userdata();
$this->load->view('header', $head_data);
$this->load->view('admin/template',$data);
$this->load->view('footer');
}

Resources