skip to Main Content

I’m facing an issue while attempting to compute the sum of data within a column named "ore" using the TSumColumn::class in Yii. The problem arises due to additional content within the cells, specifically encapsulated within <small>(' . Utility::calcoloGiornate($model->ore) . 'gg)</small>.

I aim to extract only the Yii::$app->formatter->asDecimal($model->ore) part from each cell to compute the sum at the bottom of the column. However, it’s crucial to retain the <small>(' . Utility::calcoloGiornate($model->ore) . 'gg)</small> part for display purposes in each cell.

Here’s the current column definition:

[
                    'attribute' => 'ore',
                    'value' => function ($model, $key, $index, $column) {
                        return '<span class="font-montserrat bold text-success fs-16">' 
                        . Yii::$app->formatter->asDecimal($model->ore) // only sum this value
                        . '</span> <small>(' . Utility::calcoloGiornate($model->ore) . 'gg)</small>'; //don't include this value while summing but keep it displayed in the cell
                    },
                    'format' => 'html',
                    'class' => TSumColumn::class,
                ],

Here is the TsumColumn class I’m using:

use kartikgridDataColumn;

class TSumColumn extends DataColumn
{
    public function getDataCellValue($model, $key, $index)
    {
        $value = parent::getDataCellValue($model, $key, $index);
        if (is_numeric(str_replace(',','.',strip_tags($value)))) {
            $this->footer += round(str_replace(',','.',strip_tags($value)),2);
        }
        return $value;
    }

    /**
     * Renders the footer cell content.
     * The default implementation simply renders [[footer]].
     * This method may be overridden to customize the rendering of the footer cell.
     * @return string the rendering result
     * @throws yiibaseInvalidConfigException
     */
    protected function renderFooterCellContent()
    {
        if($this->footer !== null && trim($this->footer) !== '') {
           if($this->format == 'currency') {
               return Yii::$app->formatter->asCurrency($this->footer);
           }
           return Yii::$app->formatter->asDecimal($this->footer);
        }

        return $this->grid->emptyCell;
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    I managed to solve that by extending a new class from TsumColumn and use it in my gridView table.

    class SumColumnOneValue extends TSumColumn
    {
        public function getDataCellValue($model, $key, $index)
        {
            $value = parent::getDataCellValue($model, $key, $index);
            $numericValue = 0;
    
            // Look for content within <span> tags and extract numeric values for summation
            preg_match('/<span[^>]*>([d.,]+)</span>/', $value, $matches);
            if (isset($matches[1])) {
                $numericValue = str_replace(',', '.', $matches[1]);
                $this->footer += round($numericValue, 2);
            }
    
            return $value;
        }
    }
    

  2. The main issue with your code is that you are formatting value for output in value callback instead of format callback. Because of that you have to parse already formatted html code to get value for footer.

    If you defined your column like this:

    [
         'attribute' => 'ore',
         'format' => function ($value, $formatter) {
             return '<span class="font-montserrat bold text-success fs-16">' 
                 . $formatter->asDecimal($value) . '</span> <small>(' 
                 . Utility::calcoloGiornate($value) . 'gg)</small>';
             },
         'class' => TSumColumn::class,
    ]   
    

    Then you wouldn’t need to parse html code in your TSumColumn class because parent::getDataCellValue($model, $key, $index); would return the value of $model->ore property. So your TSumColumn::getDataCellValue would simply look like this:

    class TSumColumn extends DataColumn
    {
        public function getDataCellValue($model, $key, $index)
        {
            $value = parent::getDataCellValue($model, $key, $index);
            $this->footer += round($value, 2);
            return $value;
        }
        // ... other methods ...
    }
    

    Ultimately, if the purpose of TSumColumn class is just to sum values you can get rid of it completely and sum values using array_sum and ArrayHelper::getColumn():

    [
        'attribute' => 'ore',
        'format' => function ($value, $formatter) {
            return '<span class="font-montserrat bold text-success fs-16">' 
                . $formatter->asDecimal($value) . '</span> <small>(' 
                . Utility::calcoloGiornate($value) . 'gg)</small>';
            },
        'footer' => Yii::$app->formatter->asDecimal(array_sum(
            yiihelpersArrayHelper::getColumn(
                $dataProvider->getModels(),
                fn ($model) => round($model->ore, 2),
            )
        )),
    ]
    

    Assuming $dataProvider is a variable where you have the instance of your data provider. The $dataProvider->getModels() will return array of all models on current page. I’ve used callback as second parameter in ArrayHelper::getColumn() method call to apply rounding to values of ore property.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search