Hi i am using Angular8 with Bootstrap, here i have used reactive forms, when i check on Make Default checkbox, then values present in Flowers row (Mail, Electronic,Delivery and Receipent)should be copied same to rest rows.
If the fax number format is not proper, how to show error message just below particular row recepient.
Ts:
checkAll(ev) {
const control = <FormArray>this.exampleForm.get("printList");
if (!this.all) {
this.printListArray.forEach(x => (x.value = false));
control.patchValue(this.printListArray);
} else {
this.printListArray.forEach(x => (x.value = true));
control.patchValue(this.printListArray);
}
console.log(control.value);
}
isAllChecked() {
this.all = !this.all;
}
DEMO
Your code should work more like the following
checkAll(ev) {
const control = <FormArray>this.exampleForm.get("printList");
console.log(this.all);
if (this.all) {
this.all = false;
this.printListArray.forEach(x => (x.electronics = false));
control.patchValue(this.printListArray);
} else {
this.all = true;
this.printListArray.forEach(x => (x.electronics = true));
control.patchValue(this.printListArray);
}
}
The main difference is that instead of changing the value field of x I'm changing the electronics fields, so when you are patching the form latter on, this.printListArray will have the appropriate data in the appropriate state.
In the implementation that I'm suggesting you will be able to toggle all checboxes in the row Electronics
Keep in mind that the printListArray is not an array form FormGroup/FormControl, its an array of regular objects, so the field value that usually exists in the FormControl is not present.
Related
So I have a select menu that lets the user select multiple options. the selected options correspond to actorModel.
Then I have an object array and I wish to filter it according to the selected options.
If the user selected option A and B , then it will return two objects from actorDocs.
The one that has a label value 'A' and the one that has the label value 'B'.
If no option is selected (actorModel is null) then it will return all objects from actorDocs.
The problem I am encountering in this code is that it only works if the user selects one option.
If the user selects more than one, then I tink it is trying to locate an object that has several labels instead of several objects with each label.
Any help is more than welcome
const actorModel = ref({ 0:'label1', 1:'label2', 3:'label3'})
const actorDocs = ref([{'label':'label1'},{'label':'label2'},{'label':'label3'},{'label':'label4'}])
const actorListTest2 = computed(() => {
if (actorModel.value == null){var ttt = actorDocs.value}
else {
var ttt = actorDocs.value.filter(obj => {
return (
(!actorModel.value.length || obj.label.includes(actorModel.value) )
) })}
lenActordata.value = ttt.length
return ttt
});
Try like following snippet:
const actorModel = {0:'label1', 1:'label3'}
const actorDocs = [{'label':'label1'}, {'label':'label2'}, {'label':'label3'}, {'label':'label4'}]
const actorListTest2 = () => {
if (actorModel == null){
return actorDocs
} else {
return actorDocs.filter(obj => [...Object.values(actorModel)].includes(obj.label))
}
};
console.log(actorListTest2())
I have a Jinja for loop populating one dropdown box for countries. This allows a user to select a country. But I have second Jinja for loop populating a second dropdown box for states. At the moment, the second dropdown box just iterates every state in the list (which is 1000s).
So I am building a JavaScript to iterate through the JSON file and collect the data of the user chosen country to populate the state's list with only states that are associated with that particular country.
Unfortunately, this is where I get stuck. I am not too familiar with the common concept of a for loop in JS.
So far I can pick this:
document.getElementById("country").addEventListener("change", function() {
const country_change = document.getElementById("country").value;
console.log(country_change);
console.log(countries);
});
Where country_change is the user-chosen country and countries is the entire JSON file.
Clicking on the countries log first entry I get:
This is what I want to iterate through to:
I can call all the countries from the JSON file into JS, now when a user selects a country I have that variable, so now I want to look through states for that country and its associated states.
I tried a simple for loop from w3 schools just to see what comes out - but there wasn't anything really useful that I could gather. I think I just need a bit more of a shove in the right direction.
Edit: Just experimenting with:
document.getElementById("country").addEventListener("change", function() {
const country_change = document.getElementById("country").value;
console.log(country_change);
console.log(countries);
const Ind = countries.findIndex(e => {
return e['name'] === country_change
})
if(Ind != -1){
countries[Ind]['states'].forEach(e=>console.log(e))
}
});
But still not producing the desired results.
You could do something like this:
Every time the country dropdown value changes, update all state options.
function updateSelect({ node, values }) {
while (node.hasChildNodes()) node.removeChild(node.lastChild)
for (const value of values) {
const option = document.createElement("option")
option.value = option.textContent = value
node.appendChild(option)
}
}
// Sample data
const countries = [
{
name: "Germany",
states: ["Bavaria", "Berlin", "Saxony"]
},
{
name: "Austria",
states: ["Tyrol", "Vienna"]
}
]
const coutriesSelect = document.querySelector("#country")
const statesSelect = document.querySelector("#state")
updateSelect({
node: coutriesSelect,
values: countries.map(country => country.name),
})
// Update it on initialization
updateStatesSelect()
coutriesSelect.addEventListener("change", updateStatesSelect)
function updateStatesSelect() {
const countryName = coutriesSelect.value
const country = countries.find(country => country.name === countryName)
const states = country.states
updateSelect({
node: statesSelect,
values: states
})
}
<select name="country" id="country"></select>
<select name="state" id="state"></select>
It appears this will iterate through that list and produce the states:
const Ind = countries.findIndex(e => {
return e['name'] === country_change
})
if(Ind != -1){
countries[Ind]['states'].forEach(e=>console.log(e))
}
Based on the data I have given.
I want to select one row in my first grid grid1 and the event function would then filter my other grid grid2 based on the values found in the selected row. I am using the pure javascript version of the library.
Something like
gridOptions:{
onRowSelected:my_event_filter_func,
rowData: [...],
columnDefs:[...]
}
grid1 = new agGrid.Grid(document.querySelector("#the_place"),gridOptions)
(grid2 is defined the same way based on different data and w/o the event function)
where my_event_filter_func is
my_event_filter_func = function(event) {
let my_name = event.data.name
// filter grid2 to show only the rows where the 'name' column matches my_name
}
Any help is appreciated.
I can't give you a line by line answer, and I am assuming that you are able to get your selected rows. But what I can suggest is, first, you create a copy of your the data that is on your grid2.
function copyData() {
rowData = [];
gridApi.forEachNode(node => rowData.push(node.data));
// temp is the copy of your full data in grid2
temp = [...rowData];
}
Next, on your my_event_filter_func, you can filter out the rows to be shown on grid2, based on the filtered value from grid1.
function my_event_filter_func(event) {
let my_name = event.data.name
// get the rows that do not have the matching value
const rowsToBeRemoved = temp.filter(row => row['name'] !== my_name);
// remove the rows from grid2 that do not have the matching names
gridOptions.api.updateRowData({remove: rowsToBeRemoved});
}
The source for the 2 grids is the underlying data for grid1 so it made my life easier. If that is not the case, you do need to save your base data for grid2 somewhere so that you can access it when the event gets triggered.
I ended up declaring my 2 grids as global variables and using the function below as event function :
var onSelectionChanged = function(event) {
let name = grid1.gridOptions.api.getSelectedRows()[0].name; // we know there is only one
let newRowData = grid1.gridOptions.rowData
.filter(x => x.name===name)
.map(x => {
return {
'name': x.name
// other fields...
}
})
// this overwrites grid2 data so need to save original data somewhere.
grid2.gridOptions.api.setRowData(newRowData);
grid2.gridOptions.api.refreshCells({force:true});
};
I am using the Ag-grid in my project. after came far i got to know that text inside the grid user not able to select. Is there any help i can get to select and copy the text from grid or i need to change to different plugin.
I am not in place where i can go back to different UI plugin or i can buy the Ag-grid. Need to find out some code hack for this.
I tried below hack but not work.
import {Directive, EventEmitter, Output} from '#angular/core';
import {AgGridNg2} from 'ag-grid-angular';
import {GridApi} from 'ag-grid';
#Directive({
selector: '[gridRangeRowSelection]',
})
export class AgGridSelectionDirective {
#Output('gridRangeRowSelection') onChangeEvent = new EventEmitter();
constructor(grid: AgGridNg2) {
grid.rangeSelectionChanged.subscribe(event => {
const api: GridApi = event.api;
// deselect previous rows
this.clearPreviousSelections(api);
const selectedRows = this.getSelectedRows(api);
this.onChangeEvent.emit({rows: selectedRows});
});
}
public getSelectedRows(api: GridApi) {
// get all range selections (ctrl+click/drag for multiple selections)
const rangeSelections = api.getRangeSelections();
const selectedRows = rangeSelections ? rangeSelections
.map(rangeSelection => {
let start = rangeSelection.start.rowIndex;
let end = rangeSelection.end.rowIndex;
if (start > end) {
[start, end] = [end, start];
}
// Equivalent of _.range(startRowIndex, endRowIndex).map(api.getDisplayedRowAtIndex)
const selectedRowsInRange = [];
for (let index = start; index <= end; index++) {
const selectedRow = api.getDisplayedRowAtIndex(index);
if (selectedRow) {
selectedRowsInRange.push(selectedRow);
}
}
return selectedRowsInRange;
}).reduce((a, b) => a.concat(b), []) : [];
// Unique selectedRows - as we can have multiple range selections, they may overlap rows.
const selectedRowSet = Array.from(new Set(selectedRows));
const selectedRowData = selectedRowSet.map(row => {
// note we cant use row.setSelected(true), as this will override copy to clipboard
// for cells to the whole row.
row.selected = true;
return row.data;
});
// update all newly selected and previously unselected rows
api.updateRowData({update: selectedRowData});
return selectedRowData;
}
private clearPreviousSelections(api: GridApi) {
// note this is side-effecting selection so we only do 1 pass.
const previousSelected = api['rowModel'].rowsToDisplay
.filter(row => row.selected)
.map(row => {
row.selected = false;
return row.data;
});
api.updateRowData({update: previousSelected});
return previousSelected;
}
}
https://gist.github.com/nite/dea82d184411a51fc6bc6adc7edaa422
Thanks in advance.
There is a flag which will allow you to select text and then CTRL+C will work.
[enableCellTextSelection]="true"
[ensureDomOrder]="true"
This is not an enterprise config and can be at any time to enable cell
text selection.
The above CSS fix is not working in IE>10 versions. So, I thought this would be a better solution.
Docs: https://www.ag-grid.com/javascript-data-grid/selection-overview/
#thirtydot I am not looking range selections, i am looking user can
select the few or all text from a cell.
I use this CSS for some grids where it's useful for the user to be able to select and copy part of the text in a cell:
/* enable basic browser text selection in grid cells */
div.ag-root .ag-cell-focus {
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
Some CSS that comes with ag-grid disables text selection in cells (with user-select: none;), presumably because it clashes with the range selection enterprise feature. That's not a problem for you though!
Hi am using angular 2 forms,
I have an inout field to key in users GSTIN value.
GSTIN format is XX-XXXXXXXXXX-X-X-X alphanumeric. What i need achieve is once the user keyin the values, I need to add a hyphen in to the keyed in value as per the format mentioned above.
HTML:
<custom-input [autocomplete]="false" [type]="'text'" [autocapitalize]="true" (change)="onGstinValChange($event)" (focusout)="onChangeGSTIN($event)"
[maxlength]="15" [formControl]="enterpriseDetailForm.controls['GSTIN']"
(ngModelChange)="mychange($event)"
[ngModel]="iban_no"></custom-input>
TS:
mychange(val) {
if (val) {
const self = this;
let gstin = val.split('-').join('');
if (gstin.length > 0) {
gstin = gstin.match(new RegExp('.{1,2}', 'g')).join('-');
}
console.log(gstin);
this.dataGstin = gstin;
}
}
With this function i can split every 2 values. Can someone help me on how i can achieve my format mentioned above? Thanks in advance.
Dont mix Reactive form approach with the Template drive form approach , just use one
so if you go with reactive form apporch then code will be
<custom-input [autocomplete]="false" [type]="'text'" [autocapitalize]="true" (change)="onGstinValChange($event)" (focusout)="onChangeGSTIN($event)"
[maxlength]="15" [formControl]="GSTIN"
></custom-input>
there is no need of (ngModelChange)="mychange($event)" [ngModel]="iban_no" as its template driven attributes
onGstinValChange($event){
let inputtext = $event.Traget.value;
///do code for adding - as per formate
enterpriseDetailForm.get('GSTIN').setValue(inputtext);
}
or just use reactive monitor change in value
ngOnInit() {
this.enterpriseDetailForm.get('GSTIN').valueChanges.subscribe(val =>
{
let gstin = val.split('-').join('');
if (gstin.length > 0) {
gstin = gstin.match(new RegExp('.{1,2}', 'g')).join('-');
}
enterpriseDetailForm.get('GSTIN').setValue(gstin );
}
, {emitEvent: false}));
}
html will be
<custom-input [autocomplete]="false" [type]="'text'" [autocapitalize]="true"
(focusout)="onChangeGSTIN($event)"
[maxlength]="15" [formControl]="GSTIN"
></custom-input>