yiisoft / json

JSON encoding and decoding
https://www.yiiframework.com/
BSD 3-Clause "New" or "Revised" License
26 stars 8 forks source link

Add JsExpression to processData() function like in Yii2 #23

Open aphraoh opened 3 years ago

aphraoh commented 3 years ago

What steps will reproduce the problem?

Would like to be able to use JsExpression in Yii3, like in Yii2 making it possible to json encode javascript expressions. JsExpression seems to have been removed from Yii3

What is the expected result?

Passing Javascript Expressons as a JsExpression object to Json_encode, see usage in Yii2.

What do you get instead?

This much needed functionality seems to have been removed in Yii3... unless there is another way it is now being done!?

Additional info

Q A
Version 3
PHP version n/a
Operating system all
aphraoh commented 3 years ago

Attaching possible solution which has...

Please review and merge if OK (not a GIT guru yet...)

JsonAndJsExpression.zip

samdark commented 3 years ago

I did a PR with your changes. The main issue with it is that JS expressions aren't valid in JSON so the feature doesn't fit the "json" package well.

aphraoh commented 3 years ago

Sorry, did not mean to close it...

aphraoh commented 3 years ago

Thanx for getting back, the whole point of the JSExpression class is to overcome the fact that JS Expression is not valid json and yet you might like to pass JS Expression to json and so the only place to do it would be in the JSON class, see example below, I am passing an array to a widget which json encode, it has some js expressions, what would be the solution to encode them... also not sure if I mentioned this was the solution in Yii2, off course that does not mean it is correct but there is precedence.

echo Highstock::widget([
    // The highcharts initialization statement will be wrapped in a function
    // named 'mycallbackFunction' with one parameter: data.
    'callback' => 'myCallbackFunction',
    'options' => [
        'chart' => [
            'height'=> 320,
            'backgroundColor' => '#f8f9fa',
            'borderColor'=> '#ced4da',
            'borderRadius'=> 5,
            'borderWidth'=> 0.5,
        ],
        'legend' => ['enabled' => false],
        'navigator' => ['enabled' => false],
        'scrollbar' => ['enabled' => false],
        'credits' => ['enabled' => false],
        'rangeSelector' => ['inputEnabled' => false],
        'series' => [
            [
                'name' => $series_name,
                'data' => new JsExpression('data'), // Here we use the callback parameter, data
                'type' => 'areaspline',
                'threshold' => null,
                'tooltip' => [
                    'valueDecimals' => 3
                ],
                'fillColor' => [
                    'linearGradient' => [
                        'x1' => 0,
                        'y1' => 0,
                        'x2' => 0,
                        'y2' => 1
                    ],
                    'stops' => [
                        [0, new JsExpression('Highcharts.getOptions().colors[0]')],
                        [1, new JsExpression('Highcharts.color(Highcharts.getOptions().colors[0]).setOpacity(0).get("rgba")')]
                    ]
                ]
            ]
        ]
    ]
]);
samdark commented 3 years ago

How do you plan to use Json for it?

aphraoh commented 3 years ago

Alot of js libraries have have json as input, and alot of these libraries allow js expressions in the json, for example https://www.highcharts.com

This would be the solution for that...

samdark commented 3 years ago

Can you share Highstock widget code?

aphraoh commented 3 years ago

Hi, I have attached, it is a quick hack of miloschuman's yii2-highcharts for yii2 which I hacked for yii3 as a proof of concept...

highcharts.zip

kamarton commented 2 years ago

@samdark

I did a PR with your changes. The main issue with it is that JS expressions aren't valid in JSON so the feature doesn't fit the "json" package well.

Suggest

Create an interface in this package:

interface SafeJsonEntity {
  function toJsonEntity(): string;
}

In yiisoft/html package extend it:

class JsExpression implements SafeJsonEntity {
  // ...
  function __construct(string $expression) {
    //....
  }
  function toJsonEntity() : string {
    return $this->exression;
  }
}
aphraoh commented 1 year ago

Thanx @kamarton , but tend to agree with @samdark , "...JS expressions aren't valid in JSON so the feature doesn't fit the "json" package well...", did not make sense to me then but makes sense now so closing

kamarton commented 1 year ago

@aphraoh "...JS expressions aren't valid in JSON so the feature doesn't fit the "json" package well..." BUT in web context use case is not allowed to ignore. In this package, it is sufficient to support its option, this does not affect the name of the package or standard functionality.

aphraoh commented 1 year ago

@kamarton, how does making it and interface make things different from the code I attached here... https://github.com/yiisoft/json/issues/23#issuecomment-774195673

ldkafka commented 1 year ago

I have run in a similar issue, trying to json_encode the arguments of a widget (including function/callbacks) to pass it to a JS library. The problem is that json_encode doesn't invoke any form of serializing/toString function on the JSExpression object which causes to serialize something like {'expression': 'actual JS code'} instead of {'actual JS code'}.

The magic __toString doesn't see to be called, and JSExpression doesn't implement a JsonSerializable interface.

It would be nice to just be able to json_encode the expression...

xepozz commented 1 year ago

Seems good to have JSExpression. Reopen it for more discussion

Tigrov commented 1 year ago

This could be another method for encoding data with JsExpression, e.g. Json::encodeJS() or another class / packet.

Also convert PHP DateTimeInstance instances to JS Date objects.