Open ybeunard opened 6 years ago
I am almost sure bsValueChange should be triggered on first click
Hi,
I have run a new test with bsValueChange following your tip. I have simply set (bsValueChange)="test()" in my datepicker-range. I can confirm that, on my side, the first click does not trigger the function. This function is called after the two dates have been selected and the value has been updated in my model. For your information, I’m using a form control so as to recover the value.
Best Regards YBeunard
@valorkin date rangepicke should expose one more attribute to trigger callback when first date is selected. bsValueChange triggered after date picker is done with selection of both the dates.
@valorkin Same here, can't hook to initial date click, event triggers after the full range is selected, so I am not able to pick a max or min range for x amount of days, considering the first picked date.
any progress ? I need to enable 3 Months dates starting from first selection but this is not possible without getting an event on first selection ?
I don't know how long will it take you guys to do this i found a little hack ``handleClickDateRangePicker() { setTimeout(() => { let classname = document.getElementsByClassName("bs-datepicker-body");
for (let i = 0; i < classname.length; i++) {
let idName = "bs-date-range-picker-" + i;
classname[i].setAttribute("id", idName);
document.getElementById(idName).addEventListener('click', function (event) {
console.log("CLICKED ", event);
let dd = event['toElement']['innerText'];
let junk_str = event['path'][6].innerText;
let trimmed_str = junk_str.replace(/\s/g, '');
trimmed_str = trimmed_str.replace('↵','');
let firstDigit = trimmed_str.match(/\d/);
let indexed = trimmed_str.indexOf(firstDigit);
let indexed_of_endYear = trimmed_str.indexOf('›');
let sliced_month = trimmed_str.slice(1, indexed);
let sliced_year = trimmed_str.slice(indexed, indexed_of_endYear);
console.log("FIRST DATE SELECTION ::", dd, sliced_month, sliced_year);
let start_dt = new Date(`${dd}-${sliced_month}-${sliced_year}`);
})
}
}, 1000)}
Are you planning to add this feature soon?
In the meantime, and in same vein than @mkamranhamid, I found a simpler way (but "hacky" as well) to achieve this:
// component.html
<input
(ngModelChange)="onDateRangeChange(value)"
(onShown)="onDatepickerShown()"
[maxDate]="maxDate"
[minDate]="maxDate"
[ngModel]="dateRange"
bsDaterangepicker
class="form-control date-range-input"
placeholder="Choose a date range"
type="text"
>
// component.ts
onDatepickerShown() {
const datepicker: HTMLElement = document.querySelector('bs-daterangepicker-container');
datepicker.addEventListener('click', (e: Event) => {
if ((e.target as HTMLElement).hasAttribute('bsdatepickerdaydecorator')) {
const clickedDayNum: string = (e.target as HTMLElement).innerText;
const monthYearButtons: NodeListOf<HTMLButtonElement> = datepicker
.querySelector('.bs-datepicker-head')
.querySelectorAll('.current');
const clickedDate = new Date(`${monthYearButtons[0].innerText} ${clickedDayNum}, ${monthYearButtons[1].innerText}`);
// define this.minDate & this.maxDate from clickedDate
}
});
}
However, there's 2 drawbacks (apart from the fact that's not a long-term solution 🙂):
ApplicationRef.tick
nor ChangeDetectorRef.detectChanges
. Fortunately, date range picker will re render as soon as user will hover another day Is there still no offical way to handle this issue? Are you planning to add this feature soon?
@dabbid solution works for me, here is the updated version after adding momentJS
const datepicker: HTMLElement = document.querySelector('bs-daterangepicker-container');
datepicker.addEventListener('click', (e: Event) => {
if ((e.target as HTMLElement).hasAttribute('bsdatepickerdaydecorator')) {
const clickedDayNum: string = (e.target as HTMLElement).innerText;
const monthYearButtons: NodeListOf<HTMLButtonElement> = datepicker
.querySelector('.bs-datepicker-head')
.querySelectorAll('.current');
const language = 'fr'; //assuming the current language is FR
const clickedDate = moment(`${clickedDayNum} ${monthYearButtons[0].innerText} ${monthYearButtons[1].innerText}`, 'DD MMMM YYYY', language).locale('en').toDate();
//this will disable 5 days after the clicked date
for (let index = 1; index < 6; index++) {
this.datesDisabled.push(moment(clickedDate).add(index, 'days').toDate());
}
}
});
any workaround for this yet?
really looking forward for workaround.
Any person to advance with this issue?
Someone found a workaround?
This feature would make life a lot easier for other use cases as well.
For a workaround I think better solution than access to native html elements is to read internal properties of date range picker directive.
You can inject it as @ViewChild:
@ViewChild(BsDaterangepickerDirective, {static: false}) dateRangePicker: BsDaterangepickerDirective;
And then after datepicker is opened ((onShown)="onDatepickerShown()"
) you can call custom method to watch changes of first date:
public onDatepickerShown(): void {
const datePickerInstance: BsDaterangepickerContainerComponent = this.dateRangePicker['_datepicker'].instance;
datePickerInstance.valueChange
.pipe(
filter(value => value && value[0] && !value[1])
)
.subscribe((value: Date[]) => {
const [startDate] = value;
console.log(startDate);
});
}
Hi,
I would like to submit an improvement request.
In the datepicker-range component, I would like to be able to change min date and max date values after selecting the first date.
Context: I want to grey out certain dates bases on two rules.
1- Start date must be after today but not in more than 2 years. (This can be done by setting min & max date) 2- Range should be limited to 100 days. (I would like to grey out dates that are above this range, by dynamically changing max date based on first selected date).
Having a new event sent after selecting the first date would enable more flexible and dynamic rules to be applied.
Best Regards, YBeunard