How to add Datetimepicker in ng2-smart-table - datetimepicker

I wanted to add a datetimepicker component to the ng2-smart-table component.
All I'm able to do right now is add a datepicker, but I want to add time in that as well.
I have tried with some owl-date-time component.
but it's messing up the entire window.
HTML file
<div class="input-group">
<span [owlDateTimeTrigger]="dt" class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input
[owlDateTimeTrigger]="dt" [owlDateTime]="dt"
[(ngModel)]="inputModel"
placeholder="{{placeholder}}"
[min]='min' [max]='max'
readonly
class="form-control">
</div>
<owl-date-time #dt [stepMinute]="15" [hour12Timer]='true' (afterPickerClosed)="onChange()"></owl-date-time>
**.ts file**
#Input() placeholder: string = 'Choose a Date/Time';
#Input() min: Date; // Defaults to now(rounded down to the nearest 15 minute mark)
#Input() max: Date; // Defaults to 1 month after the min
stringValue;
inputModel: Date;
constructor() {
super();
}
ngOnInit() {
if(!this.min) {
this.min = new Date();
this.min.setMinutes(Math.floor(this.min.getMinutes() / 15) * 15 );
}
if(!this.max) {
this.max = new Date(this.min);
this.max.setFullYear(this.min.getFullYear() + 1);
}
if(this.cell.newValue) {
let cellValue = new Date(this.cell.newValue);
if(cellValue.getTime() >= this.min.getTime() && cellValue.getTime() <= this.max.getTime()) {
this.inputModel = cellValue;
this.cell.newValue = this.inputModel.toISOString();
}
}
if(!this.inputModel) {
this.inputModel = this.min;
this.cell.newValue = this.inputModel.toISOString();
}
}
onChange() {
if(this.inputModel) {
this.cell.newValue = this.inputModel.toISOString();
}
}
}
#Component({
template: `{{value | date:'short'}}`,
})
export class SmartTableDatepickerRenderComponent implements ViewCell, OnInit {
#Input() value: string;
#Input() rowData: any;
constructor() { }
ngOnInit() { }
I want a date-time-picker in ng2-smart-table to choose a date and time of the day.

I solved it!!
Just follow this
https://stackblitz.com/edit/ng-date-picker-smart-table-tjvgbe .
Don't forget to add the styles in the angular.json file, just like the stackblitz link.

Related

TypeError: Cannot set property of undefined

need some support.
I want to show data by click a button or link
<div v-for="hpTheme in hpThemes" :key="hpTheme.id">
<button class="button round success" #click="showDetails(hpTheme.id)">{{hpTheme.hpTitle
}}</button>
</div>
<script>
export default {
data() {
return {
hpTheme: { hpTitle: '', hpContent: '' },
hpThemes: [
{
id: 1,
hpTitle: 'title',
hpContent: 'content'
},
{
id: 2,
hpTitle: 'title2',
hpContent: 'content2'
}
]
}
},
methods: {
showDetails(id) {
for (var i = 0; i <= this.hpThemes.length; i++) {
if (id === this.hpThemes[i].id) {
this.theme.hpTitle = this.hpThemes[i].hpTitle
this.theme.hpContent = this.hpThemes[i].hpContent
}
}
}
}
</script>
But I get this error: TypeError: Cannot set property 'hpTitle' of undefined.
How to solve?
Thanks for support.
variable i shouldn't equal to the this.hpThemes.length
for (var i = 0; i < this.hpThemes.length; i++) { // replace '<=' operator with '<'
...
}
#WilliamWang's answer is perfect to remove that error, but your code be more clean and shorter if you just pass the clicked theme as parameter then assign it to this.theme :
#click="showDetails(hpTheme)"
and
methods: {
showDetails(theme) {
this.hpTheme={hpTitle: theme.hpTitle, hpContent: theme.hpContent }
}
}
I have just changed the this.theme to this.hpTheme below. Hope this works for you.
showDetails(id) {
for (var i = 0; i <= this.hpThemes.length; i++) {
if (id === this.hpThemes[i].id) {
this.hpTheme.hpTitle = this.hpThemes[i].hpTitle
this.hpTheme.hpContent = this.hpThemes[i].hpContent
}
}
}

Countdown variable (HH:mm:ss)

I parse a date YYYY-mm-dd and calculate the difference till midnight. The result will be always under 24h, for example 10:01:10 - HH:mm:ss till it expires. I wonder how I could achieve a countdown functionality with the given example.
<template>
<Label :text="date.expires | readableTime"></Label>
</template>
filters: {
readableTime(value) {
var now = moment(new Date());
var end = moment(value);
var diff = moment.duration(end.diff(now));
try {
return moment.utc(diff.as("milliseconds")).format("HH:mm:ss");
} catch (e) {
return "00:00:00";
}
}
}
You must use use timer and reactive data property. I recommend you to safe diff to components data, start timer on component mount and clear it beforeDestroy
data() {
return {
diff: this.calculareDiff()
}
}
methods: {
calculareDiff() {
const now = moment(new Date());
const end = moment(this.date.expires);
this.diff = moment.duration(end.diff(now));
}
},
mounted() {
this.timer = setInterval(() => this.calculareDiff(), 1000)
},
beforeDestroy() {
clearInterval(this.timer)
}

Angular 5 - Event emitter (Property 'update' does not exist on type ....)

I've got a component that I want to update when a person's name changes by emitting an event. My problem is the code doesn't compile because of an error. This is my code
ApplicationFormComponent
#Output() nameChange = new EventEmitter();
closeAccordion(isComplete: string, accordionToClose: string, accordion: NgbAccordion) {
if (accordionToClose === 'personal-details-panel') {
this.applicationStatusFlags.personalDetailsStatus = (isComplete === 'true');
this.nameChange.emit({ personId: this.personId });
}
}
ApplicationFormComponent.html
<name-display
[personId]="personId"
[placeHolderText]="'Hello'"
(nameChange)="update($event)">
</name-display>
NameDisplayComponent
import { Component, Input, OnChanges, SimpleChanges } from '#angular/core';
import { PersonService } from "../../../service/person.service";
#Component({
selector: 'name-display',
templateUrl: './NameDisplay.component.html',
providers: [PersonService]
})
export class NameDisplayComponent implements OnChanges {
constructor(private readonly personService: PersonService) { }
#Input() personId;
#Input() placeHolderText: string = "";
forename: string = "";
ngOnChanges(changes: SimpleChanges): void {
if (changes["personId"]) {
this.personService.getPersonDetails(this.personId).subscribe((res: IPersonDetails) => {
this.forename = res.forenames;
});
}
};
update(personId: number) {
alert("update name");
this.personService.getPersonDetails(personId).subscribe((res: IPersonDetails) => {
this.forename = res.forenames;
});
}
}
My problem is basically when I use angular cli with the command ng server --aot, it doesn't compile because of this error:
ERROR in src\app\component\ApplicationForm\ApplicationForm.component.html(42,9): : Property 'update' does not exist on type 'ApplicationFormComponent'.
I've written a similar component that uses an event emitter which doesn't have this problem, so I'm stuck with how to fix the error.
Any ideas?
It is because you are passing $event to method.
(nameChange)="update($event)"
But it accepts number.
update(personId: number) {
alert("update name");
}
Please change the method as below.
update(event:any) {
const personId = event as number
alert("update name");
}

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: ''

I am writing a component which takes one #Input parameter and display it in the html bit I am getting below error.
SuggestionsComponent.html:54 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '<p>so string value</p>
'.
at viewDebugError (core.js:9801)
at expressionChangedAfterItHasBeenCheckedError (core.js:9779)
at checkBindingNoChanges (core.js:9948)
at checkNoChangesNodeInline (core.js:14002)
at checkNoChangesNode (core.js:13976)
at debugCheckNoChangesNode (core.js:14805)
at debugCheckDirectivesFn (core.js:14707)
at Object.eval [as updateDirectives] (SuggestionsComponent.html:54)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:14689)
at checkNoChangesView (core.js:13814)
Here is the component.
export class SuggestionsComponent implements OnInit, AfterViewInit {
#Input() suggestions: Array<Suggestions>;
#Output() approveSuggestion = new EventEmitter<Object>();
constructor(
private elementRef: ElementRef,
) {
}
ngOnInit() {
}
ngAfterViewInit() {
if (this.suggestions && this.suggestions.length > 0) {
this.suggestions
.map((value, index) => {
this.suggestions[index].newSuggestion = value.descriptionSuggestion;
});
}
}
The problem is changing component #Input variable value in ngAfterViewInit(). At that time angular changes view and making some change in bind value in upsets angular.
So moving the #input() value to ngOnInit solves the problem as its the method which executes during component bootstrap.
ngOnInit() {
// This is placed here in the in after view init is because it will throw exception as view will be change at that time
this.suggestions
.map((value, index) => {
this.suggestions[index].newSuggestion = value.descriptionSuggestion;
});
}
ngAfterViewInit() {
if (this.suggestions && this.suggestions.length > 0) {
this.suggestions
.map((value, index) => {
this.elementRef.nativeElement.querySelector('.class' + index).style.display = 'none';
});
}
}

How to use domProps in render function?

here is a custom select component, it works, but I just can not understand some part of the code,
jsFiddle
Vue.component("myselect", {
props: ['option'],
render: function (createElement) {
var self = this
var items = []
for (var i = 0; i < 16; i++) {
items.push(createElement('option', { attrs: { value: i } }, i))
}
return createElement('select', {
domProps: { value: self.option.value }, // v-bind:value = this binds the default value
on: {
input: function (event) {
console.log(event.target.value)
}
}
}, items)
}
})
this sets the default value of select to option.value, is it <select value='2'>, but the html select tag uses <option selected>, looks like magic to me.
domProps refers to element properties, not attributes.
Think of it as something like this...
document.getElementById('mySelect').value = 'Two'
<select id="mySelect">
<option>One</option>
<option>Two</option>
<option>Three</option>
<option>Four</option>
</select>
When you set the value property on a select element, it selects the option with the corresponding value (at least in Firefox and Chrome).