Closed Ofghanirre closed 1 year ago
J'oubliais, voici le code de l'exercice en question:
sandbox="python"
pieTest = :wc-chart-viewer-pies
pieTest.mode = "donut"
pieTest.data = [
{ name: "test", value: 42},
{ name: "truc", value: 30}
]
pieTest.title.text= "ahhhh"
builder==#!lang=python
==
grader==#!lang=python
==
title==
Test Charts
==
statement ==
==
form==
{{pieTest}}
==
@Ofghanirre Pour que ton code fonctionne, il manque un truc dans le template de ton composant, à savoir l'intégration du composant <wc-base [(state)]="state" />
qui s'occupe de la synchronisation du state avec les différentes manières possibles (via l'interpolation de l'input [state], via la définition explicite des props en tant qu'attribut HTML ou via une balise script). Tu n'a pas l'erreur sur la doc des composants car sur cette dernière le state d'un composant est défini via l'interpolation donc toujours détecter par angular.
<div *ngIf="commonOption" echarts [options]="commonOption" [merge]="mergedOption" class="demo-chart"></div>
<!-- IL TE MANQUAIT CETTE LIGNE -->
<wc-base [(state)]="state" />
Tu peux aussi remarquer que j'ai ajouté la prop [merge]
sur la directive echarts
. La raison est expliquée ici : https://github.com/xieziyu/ngx-echarts/issues/299#issuecomment-962883736 et sur la documentation https://xieziyu.github.io/ngx-echarts/api-doc/#api.
Je t'ai aussi simplifié le code de ton composant, je te laisse faire une diff des modifications pour comparer mais tu peux simplifier encore plus le composant:
...
du langageseries
et data
étant donné que c'est tout le temps des tableaux a priori, dans le pire des cas tu peux faire un as
...import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, Input, inject } from '@angular/core'
import { deepCopy } from '@platon/core/common'
import { EChartsOption } from 'echarts'
import { WebComponent, WebComponentHooks } from '../../web-component'
import {
ChartViewerPiesComponentDefinition,
ChartViewerPiesState,
donutChartViewerPiesState,
halfdonutChartViewerPiesState,
nightingaleChartViewerPiesState,
simpleChartViewerPiesState,
} from './chart-viewer-pies'
@Component({
selector: 'wc-chart-viewer-pies, wc-cv-pies',
templateUrl: './chart-viewer-pies.component.html',
styleUrls: ['chart-viewer-pies.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
@WebComponent(ChartViewerPiesComponentDefinition)
export class ChartViewerPiesComponent implements WebComponentHooks<ChartViewerPiesState> {
readonly injector = inject(Injector)
readonly changeDetectorRef = inject(ChangeDetectorRef)
protected commonOption = simpleChartViewerPiesState
protected mergedOption: EChartsOption = {}
@Input() state!: ChartViewerPiesState
onChangeState() {
this.state.mode = this.state.mode ?? 'simple'
this.mergedOption = {
donut: deepCopy(donutChartViewerPiesState),
simple: deepCopy(simpleChartViewerPiesState),
nightingale: deepCopy(nightingaleChartViewerPiesState),
'half-donut': deepCopy(halfdonutChartViewerPiesState),
}[this.state.mode]
if (Array.isArray(this.mergedOption.series)) {
this.mergedOption.series[0].data = deepCopy(this.state.data)
if (this.state.mode == 'half-donut') {
if (Array.isArray(this.mergedOption.series) && Array.isArray(this.mergedOption.series[0]?.data)) {
this.mergedOption.series[0].data = [
...this.mergedOption.series[0].data,
// The adding piece to hide half of the chart
{
value: this.state.data.map((element) => element.value).reduce((sum, value) => sum + value, 0),
itemStyle: {
// stop the chart from rendering this piece
color: 'none',
decal: {
symbol: 'none',
},
},
label: {
show: false,
},
},
]
// make an record to fill the bottom 50%
} else {
console.log('error')
}
}
this.mergedOption.series[0].name = this.state.dataTitle
}
this.mergedOption = {
...this.mergedOption,
title: this.state.title,
legend: this.state.legend,
tooltip: this.state.tooltip,
}
}
}
Et pour répondre à tes questions
Le state est l'objet qui est modifiable par les utilisateurs du WebComposants / widget? Oui l'input
state
est l'objet qui est modifiable par les utilisateurs sur le navigateur et les enseignants dans les graders/builders. En ajoutant le décorateur@WebComponent
sur ta classe, un getter et et setter sont crées au runtime pour détecter les changements profonds sur ton objet afin d'appeler les hooksonChangeState
et autres...Est-ce que ma façon d'ajouter des champs / properties à mes objets et correcte ? (passer d'un State à un EChartsOption...) Oui c'est la bonne manière de faire dans la méthode
onChangeState
mais tu pourrais mieux faire en faisant ça dans un pipe angular afin de rendre cette logique réutilisable si jamais tu en a besoin pour d'autres web compo.Est-ce que les widgets et les WebComponents ont un comportement différents ? Aucune différence, ils fonctionnent de la même manière, un widget est un web composant. La séparation
widgets
etforms
est là uniquement pour différencier les composants qui permettent uniquement d'afficher une donnée et ceux qui permettent de récupérer des inputs.
Par ailleurs la lib echarts
n'est pas entièrement chargée dans le navigateur, il y a un three shaking pour intégrer uniquement les fonctionnalités nécessaires dans le fichier suivant https://github.com/cisstech/platon/blob/main/libs/core/browser/src/lib/vendors/ngx-echarts/config.ts, mais je vois que tu utilise la fonctionnalité de toolbox, tu dois donc modifier la config de la manière suivante :
Hello ! J'espère que tu vas bien, j'ai récemment réaliser des widgets permettant l'affichage de charte graphique avec a librairie Echart que tu m'avais recommandé !
Je pense avoir fais tout à peu prêt correctement, et sur la page de documentation / bac à sable, tout semble fonctionner comme je le veux. (Même si je dois entièrement copier profondément certains objets)
Seulement voilà, une fois dans un exercice, le composant s'affiche, mais vide, il n'est jamais remplis, que ça soit en type script ou en python.
J'observe grâce à une balise script dans le DOM que mes données ont bien été saisies, mais c'est comme si le composant ne les recevait jamais.
C'est encore WIP mais l'objectif serait de fournir une API plus ou moins complètes pour que les utilisateurs affichent des graphes avec quelques options.
Liens:
Et globalement j'en reviens aux questions suivantes:
Cela m'intéresserait d'avoir ton avis / ta version de ce que j'ai fais. Et ça m'aidera pas mal à comprendre comment bien utiliser des widgets / composants...
Voilà voilà, je reste à ta disposition si tu as la moindre question