Reset filter value on primeNG table - primeng

According to the documentation from https://www.primefaces.org/primeng/#/table the reset method should "Resets sort, filter and paginator state."
The problem is that reset table method is not deleting the filters from UI. (although filters field from table.ts is {} after reset)
Please see the this where I reproduced it.
The code can be seen here
Filter the Summary table (see example) by Failed field (or any other field).
Press reset. => The table values will be reset but the filter value will still be visible.
The example is with the basic table but it's also NOT working with dynamic cols.
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns" [pSortableColumn]="col.field">
{{col.header}}
<p-sortIcon [field]="col.field"></p-sortIcon>
</th>
</tr>
<tr>
<th *ngFor="let col of columns">
<input pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')">
</th>
</tr>
Do you have any ideea on how I can clear the filters from the inputs?

Fixed it here
For input fields just add
[value]="dt.filters[<field>] ? dt.filters[<field>].value : ''"
where <field> is the field send in the (input) method.
(input)="dt.filter($event.target.value,<field>, 'contains')"
For example:
<th>
<input pInputText type="text" (input)="dt.filter($event.target.value, 'date', 'contains')"
[value]="dt.filters['date'] ? dt.filters['date'].value : ''">
</th>

What if you just add ngModel to your inputs like:
<input pInputText type="text" [(ngModel)]="dt22" (input)="dt.filter($event.target.value, 'date', 'contains')">
in code you'll define:
dt22:string = '';
and then onClick will be:
onClick() {
this.dt22 = '';
this.table.reset();
}
I know that this will require additional code, but this will definitely work (a just tried on your stackblitz code)

Expanding on your question about the p-multiSelects... you can fix this by binding the ngModel property to checking the value of the data table's filter. You can use this same approach for the input fields as well.
For an input field:
<input pInputText placeholder='Search'
type='text'
[ngModel]="dt.filters['foobar']? dt.filters['foobar'].value : ''"
(input)="dt.filter($event.target.value, 'foobar', 'contains')"
>
For a p-multiSelect dropdown:
<p-multiSelect appendTo="body"
[options]="[{label: 'Foo', value: 'Foo'}, {label: 'Bar', value: "Bar'}]"
[ngModel]="dt.filters['foobar']? dt.filters['foobar'].value: []"
(onChange)="dt.filter($event.value, 'foobar', 'in')">
</p-multiSelect>
Finally, calling Table.reset() will completely reset all sorting, filtering and pagination.

My solution:
(onChange)="value = $event.value === 'Reset Value' ? '' :
$event.value;
datatable.filter(value, column.field, column.filterMatchMode);
doFilter($event.value)"
Because dt.filter() with empty value will be meaning clear the filter.hope it works...

In case you are using p-calendar as a filter input and not using ngmodel :
<p-calendar pInputText #pCalendar1 *ngSwitchCase="'createdDate'"
(onSelect)="dt.filter($event, 'createdDate', 'customDateFilter')" class="p-column-filter form-control pCalendar" [dateFormat]="pCalendarFormat"
[selectOtherMonths]="true" yearRange="0000:3000" [yearNavigator]="true"
[monthNavigator]="true" [readonlyInput]="true"
[value]="dt.filters[col.field] ? datePipe.transform(dt.filters[col.field].value, dateFormat) : ''">
</p-calendar>
#ViewChild('pCalendar1') calendar1: Calendar
clearFilter() {
this.table.reset();
if (this.calendar1 && this.calendar1.inputFieldValue) {
this.calendar1.value = '';
this.calendar1.inputFieldValue = '';
this.calendar1.updateInputfield();
}
}

Related

On change ng-model value should be change

I have below code.
<td class="minwd100">
<select class="form-control" id="invoice_id" name="invoice_id" ng-options="invoice as invoice.invoice_number+ ' - '+invoice.client_name+' - '+invoice.invoice_converted_total for invoice in approved_invoices track by invoice.invoice_id" ng-model="approved_invoices.invoice_id" ng-change="changeInvoice(approved_invoices.invoice_id)"></select>
</td>
<td class="minwd100"><input type="text" class="form-control" id="payment_amount" ng-model="payment_data.payment_amount.value" name="payment_amount" placeholder="Enter {{form_data.payment_amount.label}}" ng-focus="form_data.payment_amount.error = ''" /></td>
<td class="minwd100"><input type="text" class="form-control" id="payment_conversion" ng-model="payment_data.payment_conversion_rate.value" name="payment_conversion" placeholder="Enter {{form_data.payment_conversion_rate.label}}" ng-focus="form_data.payment_conversion_rate.error = ''" /></td>
<td class="minwd100"><input type="text" class="form-control" id="payment_converted_amount" ng-model="payment_data.payment_converted_amount.value" name="payment_converted_amount" placeholder="Enter {{form_data.payment_converted_amount.label}}" ng-focus="form_data.payment_converted_amount.error = ''" ng-readonly="true"/></td>
<td class="wd80">
<div class="dt-options">
<a href ng-if="$index === form.payments.length - 1" ng-click="addContact()" title="Add Contact"><i class="fa fa-plus fa-lg"></i></a>
<a href ng-if="form.payments.length > 1" ng-click="removeContact($index)" title="Remove Contact"><i class="fa fa-trash-o fa-lg"></i></a>
</div>
</td>
<script>
$scope.changeInvoice = function (selectedItem){
$scope.payment_data.payment_amount.value = selectedItem.invoice_converted_total;
$scope.payment_data.payment_conversion_rate.value = selectedItem.invoice_conversion_rate;
$scope.payment_data.payment_converted_amount.value = selectedItem.invoice_converted_balance;
$scope.client_id = selectedItem.client_id;
$scope.payment_data.invoice_id.value = selectedItem.invoice_id;
};
$scope.addContact = function() {
$scope.form.payments.push({invoice_id: '', payment_amount: '', payment_conversion: '', payment_converted_amount: ''});
};
$scope.removeContact = function(index) {
$scope.form.payments.splice(index, 1);
};
</script>
To each change, value should be triggered for each input, But now whenever I add new row, its reflect old value itself please help. I have added image also please refere that.
What is the collection that you are iterating through?
"To each change, value should be triggered for each input, But now whenever I add new row, its reflect old value itself please help. I have added image also please refere that."
Are you saying that when you change one row every row changes? That is how I am understanding it. My guess is that all of the items in the collection are referencing the same object and you need to refer to the specific item within the collection.
I recently set up a model that had a form where you could add many associations so when adding a new association to the form I had to use a unique key to refer to the hash. I.e.:
$scope.addNewPartToAssembly = function(part) {
$scope.form.assembly.assembly_parts[part.id] = {
...
}
}
I'm just kind of guessing at your problem because to me it seems incomplete, maybe somebody else could resolve it with what's provided. Either way, hope that helps.

how to $Index get from Javascript side

how to Checked value from $index base. suppose in textboxStart Index and TextboxEnd . when user enter Start index 5 and End Index 10 , checkbox automatically checked, from 5 To 10 Index. please help me
<tr ng-repeat="item in MyList">
<td>{{$index}}</td>
<td>
<label class="mdl-checkbox mdl-js-checkbox" for="checkbox33">
<input autocomplete="off" ng-model="item.checked"
type="checkbox" id="checkbox33"
class="mdl-checkbox__input" unchecked>
{{CheckItems()}}
</label>
<td>{{item.Name}}</td>
<td>{{item.PilgrimID}}</td>
<td>{{item.GroupName}}</td>
<td>{{item.PassportNo}}</td>
<td>{{item.Gender}}</td>
<td>{{item.SubAgentName}}</td>
Use the ng-change directive to specify an update function:
<div>Input Start
<input ng-model="inputStart" ng-change="updateSelections(inputStart,inputEnd)" />
</div>
<div>Input End
<input ng-model="inputEnd" ng-change="updateSelections(inputStart,inputEnd)" />
</div>
Then update the selections:
$scope.updateSelections = function(iStart, iEnd) {
$scope.MyList.forEach((x,index)=>item.checked = (iStart<=index && index<=iEnd));
};
just push the selected values in an array , selectedItemIndexes like ng-checked="selectedItemIndexes.includes($index)"
https://stackblitz.com/edit/angularjs-snavdn
you can do it by adding one property like ItemIndex in your ItemList model,
and by putting input box with display none you can get index value in ItemList and can do what you want from javascript side,
<td><input type="text" style="display:none;" ng-model="item.ItemIndex"
ng-value="$index"/>{{$index}}
</td>

how to get select value with input values in angularjs

Can any one help how to get input and selected values by dynamically added with angularjs?
Here is my code in Plunkr
When I select vegtables, another input shows with some values. when I click submit button I need a json like
{
"itemName":"Mango",
"itemType":"fruits"
},
{
"itemName":"Carrot",
"itemType":"vegtables",
"iteminfo":"you selected Carrot"
},
{
"itemName":"Apple",
"itemType":"fruits"
}
I forked your plunker
You can bind itemInfo to an item object using ng-model. Rather than placing the text in a value attribute I just initialized the model value using ng-init.
<tr ng-repeat="item in Items">
<td>
<input type="text" ng-model="item.itemName">
</td>
<td>
<select ng-model="item.itemType">
<option value="">--Select--</option>
<option vaue="fruits">Fruits</option>
<option value="vegtables">Vegtables</option>
</select>
</td>
<td>
<div ng-switch on="item.itemType">
<input type="text" ng-model="item.itemInfo" ng-switch-when="vegtables" ng-init="item.itemInfo='you selected '+ item.itemName">
</div>
</td>
</tr>
Also I had to change the Items array to match your requested naming:
$scope.Items = [{itemName: "Mango"}, {itemName: "Carrot"}, {itemName: "Apple"}];
You can parse the JSON object in a for loop to get the selected value and add the new key value pair.
angular.forEach($scope.vegetables, function(value, key){
if(value.itemName== 'Carrot')
value.iteminfo = 'you selected Carrot';
});
I guess you might be looking for something like this, if I am not wrong.

Angular record not binding through directive

I am creating a form which you can add multiple columns which maps to an array.
An example of the record model looks like this
record = {'template_name' => 'name', 'detail_section_header' => ['Name', 'Date', 'Assigned To'}
Currently, i'm doing it like this
html:
<form>
<div class="x-label">Name</div>
<input type="text" placeholder="Name" ng-model="record.template_name" autofocus required />
<table>
<tr>
<thead ng-repeat="i in record.detail_section_header track by $index">
<input type="text" detail-section-header-input index="{{$index}}" />
</thead>
</tr>
... <buttons to add/remove columns which increments and decrements the size of detail_section_header> ...
</table>
</form>
directive in coffeescript:
angular.module('xtiri').directive 'detailSectionHeaderInput', ->
link: ($scope, el, attrs) ->
el.on('keyup', ->
$scope.record.detail_section_header[attrs.index] = el.val()
)
What is currently happening is that array (detail_section_header) doesn't populate during the key-up to the bound model (record) until I change another field in the bound model, like the template_name, then it updates. I'm guessing this has something to do with when it digests? Any suggestions on how to make that array populate instantly after typing?
Angular already has ngModel for binding to input elements, so you don't need a custom directive.
Here's how you should use ngModel to handle two-way binding:
<thead ng-repeat="i in record.detail_section_header track by $index">
<input type="text" ng-model="record.detail_section_header[$index]" />
</thead>
Note: Don't try bind to the i variable of the ngRepeat.
For example, this won't do what you expect:
<input type="text" ng-model="i" />
It would be like doing this:
(code just for demo purposes, Angular internals very different)
var detail_section_header = ['Name', 'Date', 'Assigned To'];
var $index = 0;
// This is like using `ng-model="record.detail_section_header[$index]"`
detail_section_header[$index] = 'new value';
// **Correct: **
// We get the expected result,
// `detail_section_header[$index]` has the new value
// This is the equivalent of trying `ng-model="i"`
var i = detail_section_header[$index];
i = newValue;
// **Incorrect:**
// `detail_section_header[$index]` is unchanged

Angularjs basic filtering works as union instead of intersection

I've got quite simple html table which I want to filter using several input fields. Using this structure I expect that several filled inputs would work as intersection and I'd only see details which much both conditions. But currently it is working as union, so I'am seeing any detail that matches any input text. While reading internets I saw that most people had backward problem - when similar code worked as intersection. So I am lost which behaviour is expected by default and what would the correct way to solve my task.
HTML (I am using first 4 inputs for filtering and have no special code for filtering in js part):
<div class="row" ng-controller="ItemController as ItemCtrl">
<input type="text" placeholder="Search" ng-model="searchText.$">
<input type="text" placeholder="SubmittedBy" ng-model="searchText.fields.submitted_by">
<input type="text" placeholder="Description" ng-model="searchText.fields.description">
<input type="text" placeholder="Responsible" ng-model="searchText.fields.responsible">
<div class="table-responsive">
<table class="table table-striped table-hover" id="tickets">
<thead>
<tr>
<th><input type="checkbox" ng-model="selectedAll" ng-change="checkAll()" /></th>
<th>#</th>
<th>SubmittedBy</th>
<th>Description</th>
<th>Responsible</th>
<th>DateToFix</th>
<th>DateFound</th>
<th>Fixed</th>
<th>DateFixed</th>
<th>Confirmed</th>
<th>DateConfirmed</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items | filter:(searchText||undefined)" id="{[{item.pk}]}" class="base" ng-class="{'info' : item.fields.fixed && !item.fields.confirmed, 'success' : item.fields.confirmed}">
<td><input type="checkbox" ng-model="item.selected"></td>
<td>{[{item.pk}]}</td>
<td>{[{item.fields.submitted_by}]}</td>
<td>{[{item.fields.description}]}</td>
<td>{[{item.fields.responsible}]}</td>
<td>{[{item.fields.date_to_fix | date:'EEEE, MMM d, y'}]}</td>
<td>{[{item.fields.date_found | date:'EEEE, MMM d, y HH:mm:ss'}]}</td>
<td><input type="checkbox" ng-model="item.fields.fixed" ng-change="ItemCtrl.fix(item.pk, item.fields.fixed)"></td>
<td>{[{item.fields.date_fixed | date:'EEEE, MMM d, y HH:mm:ss'}]}</td>
<td><input type="checkbox" ng-model="item.fields.confirmed" ng-change="ItemCtrl.confirm(item.pk, item.fields.confirmed)"></td>
<td>{[{item.fields.date_fix_confirmed | date:'EEEE, MMM d, y HH:mm:ss'}]}</td>
</tr>
</tbody>
</table>
</div>
I don't think that data I get from server is relevant here, but if needed I'll post it here. Considering:
(searchText||undefined)
I was using it for filtering columns with checkboxes (all, checked, non-checked) and with or without "undefined" is is working the same.
Here is there plunker link for my example: http://plnkr.co/edit/22M3Nsl36OAK2aLrJz6T?p=info
I've discovered that my issue dissappeares as soon as I exclude "fields" dict from "data" and use values likes this:
<td>{{item.submitted_by}}</td>
<td>{{item.description}}</td>
<td>{{item.responsible}}</td>
but that's what I wouldn't like to do since I'll have to change it on server side.
When you use a search expression with nested objects, Angular will return in the filtered list all items that match with at least one of the properties from those nested objects.
For example, if you have a search object like this:
{
fields: {
propA: 'bananas',
propB: 'apples'
}
}
And an object like this in the items list:
{
fields: {
propA: 'orange',
propB: 'apples'
}
}
That object will be returned by the filter as a match (despite fields.propA don't match).
Since it is not documented, I'm not sure if this is the expected behaviour or a possible bug. Nevertheless you have a way to avoid this problem, just define your own comparator:
var comparator = function(actual, expected) {
if (actual && expected && typeof actual === 'object' && typeof expected === 'object') {
var res = true;
for (var key in expected) {
if (key.charAt(0) !== '$' && hasOwnProperty.call(actual, key)) {
res = res && comparator(actual[key], expected[key]);
}
}
return res;
}
expected = (''+expected).toLowerCase();
return (''+actual).toLowerCase().indexOf(expected) > -1;
};
$scope.comparator = comparator;
And then on the HTML:
ng-repeat="item in items | filter:searchText:comparator"
Demo plunker

Resources