0

I would like to reset the properties for my ReportWidget one of two ways:

1) When the page containing the report widget is refreshed

or

2) When certain properties are changed

My ReportWidget has 3 properties: year, quarter, month

By default, I am displaying information for the current year. If a user changes the year, and then perhaps specifies a quarter or month for that year, the report displays accordingly.

Now, when they come back to the page, these settings are saved. What I would like to do is have the properties reset to their defaults when the page is reloaded or refreshed.

Furthermore, if the user changes from year to year, the other properties should reset.

I have attempted to solve this problem with this code:

public function defineProperties() {
    return [
        'year' => [
            'title' => 'Year',
            'default' => $this->getDefaultYear(),
            'group' => 'Date',
            'type' => 'dropdown',
            'options' => $this->getYearOptions(),
        ],
        'quarter' => [
            'title' => 'Quarter',
            'type' => 'dropdown',
            'group' => 'Date',
            'options' => $this->getQuarterOptions(),
            'depends' => ['month']
        ],
        'month' => [
            'title' => 'Month',
            'type' => 'dropdown',
            'group' => 'Date',
            'options' => $this->getMonthOptions(),
            'depends' => ['year']
        ]
    ];
}

public function getYearOptions() {

    $query = User::all();

    $years = [];

    foreach($query as $user) {
        $year = date('Y', strtotime($user->created_at));

        $years[$year] = $year;
    }

    $years = array_unique($years);

    return $years;

}

public function getQuarterOptions() {

    $monthCode = Request::input('month'); // Load the year property value from POST

    $yearCode = Request::input('year');

    if ($yearCode && $monthCode) {
        return;
    }

    if ($yearCode) {

        return [
            1 => '1st',
            2 => '2nd',
            3 => '3rd',
            4 => '4th'
        ];
    }
}

public function getMonthOptions() {

    $yearCode = Request::input('year'); // Load the year property value from POST

    if ($yearCode) {
        return;
    }

    $months = [];

    for ($m=1; $m<=12; $m++) {

        $month = date('m', mktime(0,0,0,$m, 1, date('Y')));

        $months[$month] = date('M', mktime(0,0,0,$m, 1, date('Y')));

    }

    return $months;
}

So what happens here is that if the year changes, it will call the getMonthOptions() function which listens for the response and if it catches the year, it will return nothing. Now this works but obviously my month list does not contain any months. I then have to close the property box and reopen it to list the months.

Are there any ideas about how I can implement this functionality? Thank you.

Larry B
  • 11
  • 1
  • 7

1 Answers1

0

hmm, i have rewrite your component and here it seems working

in init() we can reset all the value to default as we wanted, after pageload user can choose as per his requirement and widget use post requests values to calculate stuff and work according to that. but now again when user refresh page value will set to default from init() and calculation done on default values as no post values are there so,

try this one,

<?php
namespace October\Demo\ReportWidgets;

use Backend\Classes\ReportWidgetBase;
use RainLab\User\Models\User;
use Request;

class TestWidget extends ReportWidgetBase
{

    public function defineProperties() {
        return [
            'year' => [
                'title' => 'Year',
                'default' => $this->getDefaultYear(),
                'group' => 'Date',
                'type' => 'dropdown',
                'options' => $this->getYearOptions(),
            ],
            'month' => [
                'title' => 'Month',
                'type' => 'dropdown',
                'group' => 'Date',
                'options' => $this->getMonthOptions(),
                'depends' => ['year']
            ],
            'quarter' => [
                'title' => 'Quarter',
                'type' => 'dropdown',
                'group' => 'Date',
                'options' => $this->getQuarterOptions(),
                'depends' => ['month']
            ],
        ];
    }

    public function init() {

        // it will set default values on every refresh
        // we will not use $this->setProperties() as it will set
        // multiple props at single time but it will remove column size etc props as well so
        $this->setProperty('year' , $this->getDefaultYear());
        $this->setProperty('month' , '01');
        $this->setProperty('quarter' , '1st');
    }

    public function getDefaultYear() {
        // may be dynamic current year (I become sloppy here and hard coded)
        return '2018'; 
    }

    public function getYearOptions() {

        $query = User::all();

        $years = [];

        foreach($query as $user) {
            $year = date('Y', strtotime($user->created_at));

            $years[$year] = $year;
        }

        $years = array_unique($years);

        // hard-coded for testing as i don't have users so
        // $years = ['2014', '2015', '2017', '2018', '2019'];
        // $years = array_combine($years, $years);
        return $years;

    }


    public function getMonthOptions() {


        // Load the year property value from POST
        $yearCode = Request::input('year');

        // PRIORITY is user choise if he choose something this 
        // condition will be false and we dont use default property     
        // if he dosn't choose means condition true we can use default value 
        // (so it should be page refresh)
        if(!$yearCode) {

            // so if page is refreshed we use default value
            // which we set in init() method
            $yearCode = $this->property('year');
        }


        // based on $yearCode Calulate -> month
        $months = [];
        for ($m=1; $m<=12; $m++) {
            $month = date('m', mktime(0,0,0,$m, 1, date('Y')));
            $months[$month] = date('M', mktime(0,0,0,$m, 1, date('Y')));
        }
        return $months;
    }

    public function getQuarterOptions() {

        // Load the month and year property value from POST
        $monthCode = Request::input('month');
        $yearCode = Request::input('year');

        // PRIORITY is user choise if he choose something this 
        // condition will be false and we dont use default property     
        // if he dosn't choose means condition true we can use default value 
        // (so it should be page refresh)
        if (!$yearCode && !$monthCode) {

            // so if page is refreshed we use default value
            // which we set in init() method
            $yearCode = $this->property('year');
            $monthCode = $this->property('month');
        }


        // now based on $yearCode and $month code calulate -> quarter
        if ($yearCode) {
            return [
                1 => '1st',
                2 => '2nd',
                3 => '3rd',
                4 => '4th'
            ];
        }
    }

    public function render()
    {
        return $this->makePartial('widget');
    }
}

if you get any issue please comment.

Hardik Satasiya
  • 9,547
  • 3
  • 22
  • 40
  • I think were headed in the right direction. I changed it so it sets the month and quarter to null in the init() function. Now whenever I change the year, I need it to set the month and quarter to null as well, but still have the list available. – Larry B Jan 19 '18 at 17:40
  • but you said `If a user changes the year, and then perhaps specifies a quarter or month for that year, the report displays accordingly.` - so if list will be null then how user can select quarter or month – Hardik Satasiya Jan 22 '18 at 01:05
  • even better can you share example data (combinations and cases) how you need it so we can do like that – Hardik Satasiya Jan 22 '18 at 07:15