0

Update:

I checked if setDate() is called from ngOnInit: it is.

Also I specified the variables: rentalStartInput is an string Array and contains the real dates with I get from the other component (see picture below).

rentalStart is a Date, right now it is hard-coded, which I want to change. rentalStart should countain the start day of a range which I got from rentalStartInput. Current I write it manually, to see if highlighting dates works. (it does)

Update end

I'm a beginner with typescript/angular and I'm having the problem of not being able to access variables.

I have some rentals which have a start and end date. I want to display those in a calendar like the following: calender with highlighted range

Currently I get it out that the range is displayed as in the picture, but only hard-coded. TypeScript:


@Component({
  selector: 'app-calendar',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements OnInit {

 // @Input() rentalStartInput: String[]; //error: Property 'rentalStartInput' has no initializer and is not definitely assigned in the constructor.
    @Input() rentalStartInput: String[] = [];
    @Input() rentalEndInput: String[] = [];
    rentalStart: Date = new Date(2023-1-1);
    rentalEnd: Date = new Date(2023-1-1);

    getDaysFromDate(month: number, year: number) {

        const startDate = moment(`${year}/${month}/01`)
        const endDate = startDate.clone().endOf('month')
        this.dateSelect = startDate;

        const diffDays = endDate.diff(startDate, 'days', true)
        const numberDays = Math.round(diffDays);

        this.monthSelect = Object.keys([...Array(numberDays)]).map((a: any) => {
          a = parseInt(a) + 1;
          const dayObject = moment(`${year}-${month}-${a}`);
          return {
            name: dayObject.format("dddd"),
            value: a,
            indexWeek: dayObject.isoWeekday(),
            selected: this.isInRange(a, month, year),
          };
        });
      }

    isInRange(day: any, month: any, year: any) {

        let rangeDay = new Date(year, month - 1, day); 

        this.rentalStart = new Date(2023, 0, 6); //hard-coded, what I want to change
        this.rentalEnd = new Date(2023, 0, 17)

        let rentalRange = moment.range(this.rentalStart, this.rentalEnd);

        return rentalRange.contains(rangeDay); //true if day is in range -> highlighted in ui
    } 
}

When I try to get access to variables rentalStartInput and rentalEndInput it doesnt work. I want to replace rentalStartand rentalEnd with them. I also don't want to do the assignment within the method, because then it's done 31 times. But when I change it to a new method, rentalStart and rentalEnd are undefined. How can I assign both variables and use them in isInRange?


@Component({
  selector: 'app-calendar',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements OnInit {
    @Input() rentalStartInput: String[] = [];
    @Input() rentalEndInput: String[] = [];
    rentalStart: Date = new Date(2023-1-1);
    rentalEnd: Date = new Date(2023-1-1);

    ngOnInit(): void {
        this.setDate();
    }

    setDate(){
        this.rentalStart = new Date(2023, 0, 6);
        this.rentalEnd = new Date(2023, 0, 17);
        console.log('setDate'); //check if it is ever called from   ngOnInit (it is)
    }

    isInRange(day: any, month: any, year: any) {
        console.log(this.rentalStart); // undefined
        (...)
    }
}

I get the real dates from another component via @Input(). They are in separate variables: rentalStartInput and rentalEndInput In console they look like this:

screenshot from input

What i'm trying to do is to generate range objects to check if a day is included. First of all, I fail getting access to the dates.

console.log(this.rentalStartInput) // see picture
console.log(JSON.stringify(this.rentalStartInput)) // []
console.log(this.rentalStartInput[0]) // undefined
console.log(Object.keys(this.rentalStartInput).length) // 0
console.log(this.rentalStartInput.length) // 0
console.log(this.rentalStartInput['1']) // undefined

What possibilities are there to access the data? I cant do a for loop unless I know the length of the array.

I hope my problem is understandable. I can provide more code if necessary.

Thank you very much for any kind of help!

Mia
  • 17
  • 6
  • 2
    If you log an array or object and you feel that there's something odd in the log, try `console.log(JSON.stringify(this.rentalStart))` instead. For objects and arrays the log shows the value it has a view-time instead of log-time, so when it is updated after logging you see the updated values in the log. `JSON.stringify` makes it a string when logging, so it really shows the value it had at the time of logging – A_A Jan 28 '23 at 12:34
  • 1
    When you do `this.rentalStart = new Date(2023, 0, 6);` in a function, you actually set `rentalStart` property value of the function. Every function is an object, and you are setting its property instead of setting `rentalStart` declared outside. You either need to remove `this.` or you need to put this functions into a class and declare your `rentalStart` and other fields as properties of the class. In this case you will be able to use `this` and it will be shared among functions/methods. – RAllen Jan 28 '23 at 12:37
  • Thank you @A_A ! When I try this i got `[]` which would be the reason why length = 0 I guess – Mia Jan 28 '23 at 12:44
  • Thank you @RAllen ! What would be the better way? I'm not sure I fully understand the class thing. Could you give an example? – Mia Jan 28 '23 at 12:57
  • 1
    @Mia, actually, I have a different thought now. Add a `console.log` into `setDate` and check if it is ever called from `ngOnInit`. It feels like it doesn't. Second but actually more important thing: never use `any` in TypeScript. The whole point of TypeScript is types. Strict types help you to avoid unexpected values. For example, you declare `rentalStart: any;` and assign `this.rentalStart = new Date(2023, 0, 6);` but then do this `console.log(this.rentalStart[0]) // undefined`. Is `rentalStart` an array or just a `Date`? Update your question with these fixes first. – RAllen Jan 28 '23 at 22:10
  • 1
    @RAllen `setDate` is called from `ngOnInit`. I've updated the question and (hopefully) explained the types of the variables better. Thank you!! – Mia Jan 29 '23 at 09:20
  • @Mia, yes, the question has improved. What is a bit strange to me is that `@Input() rentalStartInput: String[] = [];` declares binding of property `rentalStartInput` with control, but you also initialize it with `[]`. Can you try to remove `=[]` and keep only the declaration? Also, do you have a `class` that wraps this code? Do you have a `@Component` declaration above the class? If you have a class and a component declaration, please add them to the code in the question. They are important to resolve this issue. – RAllen Jan 29 '23 at 13:56
  • 1
    @RAllen When I remove `=[]` I got an error: `TS2564: Property 'rentalStartInput' has no initializer and is not definitely assigned in the constructor.` I have a `class` and a `@component` declaration, which I added to the code in the question. I hope this helps. Thank you! – Mia Jan 29 '23 at 14:15
  • @Mia, okay, thanks. Please check `input` doc here https://angular.io/api/core/Input Scroll to the section `Usage notes`. Notice how `bankName` in the component is bound to `@Input() bankName: string;`. Is this pattern implemented in your case? Your component has `./calendar.component.html` as a template and I'm not sure if this `html` contains a field that will be populated for `@Input() rentalStartInput` in order to fill it with data as you expect. Also, you expect to bind an array of dates. It is a more complex scenario than binding a string, for example. Check the array binding. – RAllen Jan 30 '23 at 07:10

0 Answers0