PrimeNG - Filter table by indexed element of property array - datatable

I want to implement data filtering in a PrimeNG table, according to an indexed element of a property of my model.
Model example in JSON format below:
{
"customObj":{
"id":1,
"name":"my name",
"labels":[
{
"id":1,
"labelValue":"A random label"
},
{
"id":2,
"labelValue":"A random label 2"
}
]
}
}
Considering the model above, I would like to filter the table by customObj.labels[0].labelValue property.
Which is the most out of the box way to achieve this in a PrimeNG table?
Until now I used for single object properties filtering the columnFilter component as shown below
<!-- example of filtering for the name property -->
<th>
<p-columnFilter type="text" field="name"></p-columnFilter>
</th>
can I use something similar to this? I have read the PrimeNG documentation but did not find any example on this. Thanks in advance
Angular version: 12.2.3
PrimeNG version: 12.1

The simplest solution I finally found to filter the table by indexed element of array property is using the <p-columnFilter as shown below:
<!-- Filter customObj by 'labels[0].labelValue-->
<th>
<p-columnFilter type="text" field="labels.0.labelValue"></p-columnFilter>
</th>
If the index is in variable form and we do not know it beforehand you can also use variable as shown below:
<!-- Filter customObj by 'labels[index].labelValue-->
<th>
<p-columnFilter type="text" field="labels.{{index}}.labelValue"></p-columnFilter>
</th>

Related

Display tag external sort overriden?

I am using display tag and spring mvc.
Basically, i have a simple table like this. Note the use of external.
<display:table id="tableId" name="data" sort="external" defaultsort="1" sort="external">
<display:column property="id" title="ID" sortable="true" sortName="id" />
<display:column property="firstName" sortable="true" sortName="firstName" title="First Name" />
<display:column property="lastName" sortable="true" sortName="lastName" title="Last Name" />
<display:column property="address" sortable="true" sortName="address" title="Email Address"/>
</display:table>
On the controller side, i get the sorted column index and the sort order.
String c = request.getAttribute(new ParamEncoder("tableId").encodeParameterName(TableTagParameters.PARAMETER_SORT));
To get the order (ASC/DESC):
String order = request.getAttribute(new ParamEncoder("tableId").encodeParameterName(TableTagParameters.PARAMETER_ORDER)));
All this is working fine. For the last step i used customized comparator to sort my list and put it back into the attribute "data" mapped himself to the table (see display tag "name" property).
public void populateModel(Model model, HttpRequest request){
String c = request.getAttribute(new ParamEncoder("tableId").encodeParameterName(TableTagParameters.PARAMETER_SORT));
// here the comparator is computed with column and order value eg
Comparator comp = new DefaultComparator();
if(c == 1){
comp = new NumericComparator();
}
List<Employe> list = Collection.sort(dao.getEmployee(), comp );
model.addAttribute("data", list);
// here the list is sorted properly
return "mypage";
}
Unfortunatly the display in the final jsp does not care about order in the list. It seem's something is overriding to a default and alphanumeric sorter...so even if i use my NumericComparator the column is still wrong sorted and i assume the "list" object has been sorted back by the librairie before the display.
To summup:
Get display tag indexes : ok
Sort the list and put it back to jsp : ok (list is sorted depending on display tag params in the controller)
Display the sorted list in the jsp side with display tag : KO (the library do not care about list order, sorting it with default sort)
Display the sorted list in the jsp side without display tag : OK
Any got the explanation about this, is there something wrong or missing ?

Update smart table after content changed

I have an array of objects, which I display using st-table directive.
I filter the table by a value of a certain field in the objects.
The problem is, once a value of a field in these objects has been changed, the filtering is not performed.
I believe the reason for it is that smart-table watches the array's length, but doesn't perform deep comparison to see whether or not the values inside any of the objects changed.
What can I do to solve this?
edit: added code:
angular.module('myApp', ['smart-table'])
.controller('mainCtrl', ['$scope', '$timeout',
function ($scope, $timeout) {
$scope.rowCollection = [
{
name: "sth odd",
number: 1
},
{
name: "sth even",
number: 1
}
];
$scope.displayedCollection = [].concat($scope.rowCollection);
function changeNumber(){
$timeout(function(){
$scope.rowCollection[1].number = $scope.rowCollection[1].number === 1 ? 2 : 1;
changeNumber();
}, 1000);
}
changeNumber();
}
]);
http://plnkr.co/edit/IVYy5WrsiEJSRXZCqY9z?p=preview
Notice how when you search e.g number "2", the view isn't updated even though the property of the second item sometimes is "2" and sometimes not.
Found a solution for you, instead of using st-search use a plain ng-model and then filter by the ng-model value. then in the ng-repeat filter by that value
so instead of this
<input st-search="number" placeholder="search for number" class="input-sm form-control" type="search"/>
...
<tr ng-repeat="row in displayedCollection">
<td>{{row.name}}</td>
<td>{{row.number}}</td>
</tr>
do this
<input ng-model="searchMe" placeholder="search for number" class="input-sm form-control" type="search"/>
....
<tr ng-repeat="row in filterd = (displayedCollection | filter: searchMe)">
<td>{{row.name}}</td>
<td>{{row.number}}</td>
</tr>
here's a plunker, enter 2 and see how it redos the filtering each time
To refresh the smart-table you can add or remove items as you know or use a new array.. so just recreate the array.
$scope.rowCollection = [].concat($scope.rowCollection);

How to get checked checkbox value from html page to spring mvc controller

im using spring mvc framework with thymeleaf template engine
the problem is , i have 1 page with multiple check box iterated sing thymeleaf th:each iterator.When i clicked multiple check boxes i want to pass check box values to the controller method..
html content
<table>
<tr th:each="q : ${questions}">
<h3 th:text="${q.questionPattern.questionPattern}"></h3>
<div>
<p >
<input type="checkbox" class="ads_Checkbox" th:text="${q.questionName}" th:value="${q.id}" name="id"/>
</p>
</div>
</tr>
</table>
*Controller*
#RequestMapping(value = Array("/saveAssessment"), params = Array({ "save" }))
def save(#RequestParam set: String, id:Long): String = {
var userAccount: UserAccount = secService.getLoggedUserAccount
println(userAccount)
var questionSetQuestion:QuestionSetQuestion=new QuestionSetQuestion
var questionSet: QuestionSet = new QuestionSet
questionSet.setUser(userAccount)
questionSet.setSetName(set)
questionSet.setCreatedDate(new java.sql.Date(new java.util.Date().getTime))
questionSetService.addQuestionSet(questionSet)
var list2: List[Question] = questionService.findAllQuestion
var limit=list2.size
var qustn:Question=null
var a = 1;
for( a <- 1 to limit ){
println( a );
qustn= questionService.findQuestionById(a)
questionSetQuestion.setQuestion(qustn)
questionSetQuestion.setQuestionSet(questionSet)
questionSetQuestion.setCreatedDate(new java.sql.Date(new java.util.Date().getTime))
questionSetQuestionService.addQuestionSetQuestion(questionSetQuestion) } "redirect:/teacher/Assessment.html" }
I think you pretty much have it. With a checkbox, you can only send one piece of information back with the form...that being the value. So if you are trying to determine which checkboxes are checked when the user clicks the submit button, then I would have the checkboxes all use one name...like "id" (exactly like you have). Value is the actual id of the question (again like you have). Once submitted, "id" will be a String array which includes all the values of the checkboxes that were checked.
So your controller method needs to take param called "ids" mapped to parameter "id" which is a string[]. Now for each id, you can call questionService.findQuestionById.
(I'm not a Groovy guru so no code example sry :)
I have used JSTL with JSP and thymeleaf was something new. I read the THYMELEAF documentation.
There is a section which explains multi valued check boxes.
<input type="checkbox"
class="ads_Checkbox"
th:text="${q.questionName}"
th:value="${q.id}" name="id"/>
In the above code we are not binding the value to the field of the command object. Instead try doing this
<input type="checkbox"
class="ads_Checkbox"
th:text="${q.questionName}"
th:field="*{selectedQuestions}"
th:value="${q.id}" />
here the selectedQuestions is an array object present in the spring command object.

Stripes Checkboxes and Textfields

All -
I'm using stripes to do some form input for a problem I'm working on and I'm stuck on how best to submit a a pair of data using stripes and checkboxes.. for example my page looks like the following:
I have a list of options where users can enable a selection by clicking the box, and also supply some input for that item by entering data into the text field next to it:
<tr>
<td><stripes:checkbox name="item.enable" value="${item.id}"/></td>
<td><stripes:text name="item.value" value="${item.value}"/></td>
</tr>
.....
next item...
When the form is submitted I'd expect my Collection<Item> to be populated yet that's not the case..
How can I best submit a pair of items using the check box fields.
Thanks in advance.
..Chris
Read the documentation on indexed properties. You need to tell Stripes that you have multiple items, by naming them items[0], items[1], etc.:
<tr>
<td><stripes:checkbox name="items[0].enable" value="${item.id}"/></td>
<td><stripes:text name="items[0].value" value="${item.value}"/></td>
</tr>
<tr>
<td><stripes:checkbox name="items[1].enable" value="${item.id}"/></td>
<td><stripes:text name="items[1].value" value="${item.value}"/></td>
</tr>
This supposes that you action bean has a setItems(List<Item> items) method, that the Item class has a public no-arg constructor, and has a setEnable(String itemId) and a setValue(String value) method.
I would wrap this in a JSTL 'forEach' tag and I would put the items in a List. Similar to what JB Nizet said, you also need public setters in the action bean. If you are using Collection<Item> with some implementation other than List<Item> the below snippet won't work.
<c:forEach var='itemIndex' begin='0' end='2'>
<c:set scope='page' var='item' value='${items[itemIndex]}'>
<tr>
<td><stripes:checkbox name="items[${itemIndex}].enable" value="${item.id}"/></td>
<td><stripes:text name="items[${itemIndex}].value" value="${item.value}"/></td>
</tr>
</c:forEach>
There is another case when you don't want the list to default to 3 items. The one I'm thinking of is when the list is already populated. If that is the case I would change the 'end' attribute of the <c:forEach> to be: ${fn:length(actionBean.items) == 0 ? 3 : fn:length(actionBean.items)-1}

MVC3 WebGrid: Can htmlAttributes be used on rows/columns?

I'm using a WebGrid to create a paged/sortable list in MVC3. I've created an AJAX enabled Delete button which makes the delete call via AJAX, after which I'd like it to remove the row from the table.
The way I'd like to achieve this is by having an id or data-id attribute on the <tr> in the table so that I can easily manipulate it using jQuery. However I can't work out how to add attributes to rows when using a WebGrid.
I know that attributes can easily set at the grid level like so:
#grid.GetHtml(htmlAttributes: new { id = "gridMapping", style = "width:100%;" },
However I don't know how to achieve the same at the row/column level.
#grid.GetHtml(
columns: grid.Columns(
grid.Column(format: (item) => Html.CheckBox("SelectedInvoice",new { value=item.transactionId})),
//// rest of your columns here
)
)
so one way would be putting an HTML helper method in place that can handle your htmlAttributes.
Other way - using combination of format: and Html.Raw
And the last, but may be the easiest: javascript (jQuery)
so you can try something like :
$('#grid tr').each(function(){
$(this).attr('yourhtmlattribute','value');
});
and in similar way for TDs.
Here is how I achieved this
In your webgrid set up add this to one of the colums.
grid.Column("UserName", "User Name", format: #<text><span data-id='#item.Id'>#item.UserName</span></text>, canSort: true),
No when the HTML grid is rendered you will get this.
<tr jQuery45435434="3"> <span data-userid="1">Fred Smith</span></tr>
<tr jQuery45435434="4"> <span data-userid="2">Sally Smith</span></tr>
<tr jQuery45435434="5"> <span data-userid="3">Joe Smith</span></tr>

Resources