Comment créer un widget enfichable avec une barre de progression circulaire
Ce n'est pas souvent que j'ai l'occasion de créer des widgets enfichables dans ma vie quotidienne, donc pour garder mes compétences à jour, j'aime me mettre au défi en essayant de recréer un widget que j'utilise régulièrement. Cela fait un moment que je n'ai pas fait cela, alors cette semaine j'ai décidé de tester mes compétences et d'essayer de recréer le widget Circular Progress Bar, qui est fourni dans les modules de ressources mobiles natives. Alors attachez vos ceintures et partons à la découverte du monde de React et Mendix.
Avant de commencer
Veuillez prendre un moment avant de continuer, pour vous assurer que tout est configuré avant de commencer. Vous aurez besoin de :
- Mendix Studio Pro (j'ai utilisé (9.1.1) dans cet exemple.
- Node js installé et configuré sur votre machine.
- Votre IDE de choix, j'ai utilisé VS Code pour cela.
- Il est recommandé d'avoir complété ceci tutoriel sur les widgets enfichables à partir de la documentation ou vous avez terminé ceci cours de l'académie.
- Le Faites-le natif 9 Application installée sur votre appareil de test
Choisir une bibliothèque GitHub à utiliser
Savoir par où commencer avec un projet comme celui-ci peut parfois être intimidant pour un développeur, c'est pourquoi je trouve qu'il est beaucoup plus facile de savoir quoi faire après quelques recherches. Je suis donc allé sur github et j'ai regardé ce qui existait déjà. Je suis tombé sur ce dépôt de académie d'épicode J'ai décidé de l'utiliser comme base pour mon composant. Ce dépôt contient d'autres projets, donc si vous cherchez le lien exact, c'est ici. ici.
Analyse du code
Avant de commencer à coder, il est important de revoir le code fourni et de vous assurer que vous comprenez ce qui se passe. En regardant l'exemple, je peux déjà voir qu'il utilise des composants fonctionnels, et je sais que cela nécessitera quelques modifications pour être implémenté dans un widget enfichable car le composant principal est normalement un composant de classe.
Les composants sont de deux types : les composants de classe et les composants de fonction. Un composant fonctionnel est simplement une fonction JavaScript simple qui accepte les props comme argument et renvoie un élément React. Un composant de classe nécessite une extension de React.
Création de l'échafaudage du widget
Assez lu, passons au code ! Pour commencer, ouvrez votre terminal et accédez au répertoire de votre projet. Un moyen rapide de le faire est de cliquer sur « Afficher le répertoire de l'application dans l'explorateur » sous « Application » dans le menu supérieur de Studio Pro. Cela ouvrira un explorateur de fichiers contenant les fichiers de votre application. Copiez le chemin d'accès au fichier dans la barre de navigation, puis revenez au terminal que vous avez ouvert. Tapez « cd » et collez le chemin d'accès au fichier comme ceci :
cd yourFilePath
Ensuite, nous devons créer un dossier pour stocker les widgets personnalisés. Dans votre terminal, tapez :
mkdir CustomWidgets
Et puis utilisez cd pour aller dans le dossier que vous venez de créer :
cd CustomWidgets
Vous pouvez maintenant utiliser le générateur de widgets pour créer l'échafaudage du widget pour vous. Dans le terminal, utilisez à nouveau cette commande pour appeler le Mendix générateur de widgets :
@mendix/widget CircularProgressBar
Le générateur de widget vous guidera ensuite dans la création du widget en vous posant quelques questions, voici ce que j'ai utilisé :
- Nom du widget : {Le nom de votre widget}
- Description du widget : {Description de votre widget}
- Nom de l'organisation: {Le nom de votre organisation}
- Droits d'auteur: {Votre date de copyright}
- Licence: {Votre permis}
- Version initiale:{Votre numéro de version initiale}
- Auteur : {Votre nom d'auteur}
- Mendix Chemin du projet : ../../
- Langage de programmation: javascript ES6
- Type de widget : Mobile natif
- Modèle de widget : Widget vide (recommandé pour les développeurs plus expérimentés)
- Tests unitaires : Non
- Tests de bout en bout : Non
Configuration du widget XML
La première chose que nous devons faire est de modifier le XML du widget afin que nous puissions recevoir des données de l'entité de contexte sous la forme d'un attribut. Pour ce faire, nous devons créer une propriété qui peut accepter une valeur entière. Il est également important de définir la valeur clé de cette propriété. Vous pouvez voir mon XML de widget ci-dessous.
<?xml version="1.0" encoding="utf-8"?>
<widget id="mendix.circularprogressbar.CircularProgressBar" needsEntityContext="true" offlineCapable="true" pluginWidget="true"
supportedPlatform="Native" xmlns="https://www.mendix.com/widget/1.0/"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.mendix.com/widget/1.0/ ../node_modules/mendix/custom_widget.xsd">
<name>Circular Progress Bar</name>
<description>Animated Circle Progress widget</description>
<icon>
iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABp1BMVEUAAABV//9mzP9LtP9Ms/9Jtv9NsvdJsfpLtPpJsfdJsfhJsvhJsvdKsvdJsPhKsPhJsfdJsPhJsfdIsfhJsfdIsPdJsfhJsfhJsPhJsPhIsfhIsPdJsPdKsPdKsfdNsvdOsvdPs/dQs/dRtPdStPdTtPdUtfdWtvdXtvdauPdcuPdeufdeufhguvhiu/hju/hkvPhmvfhnvfhpvvhrv/huwPhvwfhxwfhywvhzwvh4xfl5xfl6xfl8xvl9xvl9x/mByPmCyfmFyvmGyvmJzPmKzPmLzfmNzvqPzvqQz/qT0PqU0PqU0fqX0vqY0vqa0/qe1fqg1vqj1/uk1/un2fup2vut2/uv3Puw3Puw3fuz3vu13/u23/u34Pu44Pu64fu64fy84vy94vy+4/y/4/zD5fzE5fzG5vzH5vzI5/zK6PzL6PzR6/zT7P3U7P3V7f3W7f3Y7v3Z7v3c8P3e8f3f8f3g8f3i8v3l8/3l9P3n9P3r9v7t9/7u9/7v+P7w+P7x+f7y+f70+v71+v74/P75/P76/f77/f78/f78/v79/v7+/v7////6dMsRAAAAG3RSTlMAAwURGxwhMTNic3SEh4iVp7XBzejt7vH5/f6PsMNWAAABsklEQVR4AWIYfGAUjIJRMAqYuYREJKWJAqLCPGwY+jnFpEkBEryMqPr5pEkFgkwo9kuTDviR/S9GhgFSHAgDuKXJAQIIA4TIMkAcEY4i0mQBVrgBkuQZwA43QJo8wIFhQEhEOIBQOutHJozDOP5Crp4e1RhkJ0tKGJFd6oNEdtmJyEIzpaZl5nrRZgaHM/2Pf5/vwXXfyagXgG93bwSAlEolowLMm9w83gibhXH2gKKVdD67gTnWjwCk+VVjMQS4suSnnjMLRVFc9sAHvAX2A9fySaXNBMbEZVUWscaHIMRuqwBgD8hDEbnsRmfjUKJkAQZGCTlO/xWBwIADQLIZBlY441MvfoF1xlFS/4fy+bzXKh4dgNJE7L3eh3tmtuWa+AMcMIY3dgUvZQpGEYmMw2kD7HC+R29UqyoXLaBd0QZxzgXgikLLDSqJTKU5HOcS0MsbA9jPqtwCRvXm2eorBbNIJBw3KJ9O4Yl+AAXdnyaLt7PWN3jRWLvzmAVp94zO5+n41/onfo/UpExxZqI0O7NQr0DhIq9Io7hQpbRYp7hiobRqo6ByFcNWuY6CUTAKRgEAo8X0lBD3V30AAAAASUVORK5CYII=
</icon>
<properties>
<propertyGroup caption="General">
<property key="progress" type="attribute" required="true">
<caption>Progress Indicator</caption>
<description>The attribute that contains the circularprogressbar value, should be an integer between 0 and 100</description>
<attributeTypes>
<attributeType name="Integer"/>
</attributeTypes>
</property>
</propertyGroup>
</properties>
</widget>
Le composant principal
Maintenant que nous avons défini les données d'entrée, nous pouvons travailler sur le composant principal. Dans ce cas, le composant principal est simplement destiné à restituer le composant enfant et à lui transmettre les données fournies par l'utilisation de ses accessoires.
« Props » est un mot-clé spécial dans React, qui signifie propriétés et est utilisé pour transmettre des données d'un composant à un autre. Mais ce qui est important ici, c'est que les props de données sont transmises uniquement dans un flux unidirectionnel (à sens unique).
Il convient de noter ici que, comme indiqué précédemment, le composant principal est créé dans l'échafaudage en tant que composant de classe. Cela signifie que nous devons légèrement modifier le code Github.
Voici le code de mon composant principal appelé CircularProgressBar.
import { React,Component ,createElement} from "react";
import CircularProgress from "./components/CircleComponent";
export class CircularProgressBar extends Component {
constructor(props){
super(props);
this.handleChange =this.handleChange.bind(this);
const {progress} = this.props;
console.log('constuctor triggered');
}
render() {
const {progress} = this.props;
console.log('render triggered');
return (
<CircularProgress
progress={progress.value}
size={200}
/>
)
}
}
Le composant enfant
Le composant enfant est l'endroit où se déroule l'essentiel de notre logique. Ici, nous acceptons les données du composant parent en utilisant à nouveau des accessoires, un peu de logique et la bibliothèque de style de « styled-components/native » pour styliser les éléments individuels qui composent la barre de progression. Enfin, nous terminons par une instruction de retour qui doit restituer le composant. Vérifiez le code du composant enfant « CircleComponent » ci-dessous.
import React, { useRef, useEffect, createElement } from "react";
import styled from 'styled-components/native';
import {Animated} from 'react-native';
const EmptyColour = '#a0a0a1';
const ProgressColour = '#0085ff';
const CircleBase = styled(Animated.View)`
width: ${props => props.size}px;
height: ${props => props.size}px;
border-radius: ${props => props.size / 2}px;
border-width: ${props => props.size / 10}px;
`;
const EmptyCircle = styled(CircleBase)`
border-color: ${EmptyColour};
justify-content:center;
align-items: center;
transform: rotate(-45deg);
`;
const Indicator = styled(CircleBase)`
position: absolute;
border-left-color:${ProgressColour};
border-top-color:${ProgressColour};
border-bottom-color:transparent;
border-right-color:transparent;
`;
const CoverIndicator = styled(CircleBase)`
position: absolute;
border-left-color:${EmptyColour};
border-top-color:${EmptyColour};
border-bottom-color:transparent;
border-right-color:transparent;
`;
export default function CircularProgress(props) { //added input props
const {progress, size} = this.props //destructured the props
console.log (styled)
const animatedProgress = useRef(new Animated.Value(0)).current;
const animateProgress = useRef(toValue => {
Animated.spring(animatedProgress, {
toValue,
useNativeDriver: true,
}).start();
}).current;
useEffect(() => {
animateProgress(progress);
}, [animateProgress,progress]);
const firstIndicatorRotate = animatedProgress.interpolate({
inputRange: [0, 50],
outputRange: ['0deg', '180deg'],
extrapolate: 'clamp',
});
const secondIndicatorRotate = animatedProgress.interpolate({
inputRange: [0, 100],
outputRange: ['0deg', '360deg'],
extrapolate: 'clamp',
});
const secondIndictorVisibility = animatedProgress.interpolate({
inputRange: [0, 49, 50, 100],
outputRange: [0, 0, 1, 1],
extrapolate: 'clamp',
});
return (
<EmptyCircle size={size}>
<Indicator
style={{transform: [{rotate: firstIndicatorRotate}]}}
size={size}
/>
<CoverIndicator size={size} />
<Indicator
size={size}
style={{
transform: [{rotate: secondIndicatorRotate}],
opacity: secondIndictorVisibility,
}}
/>
</EmptyCircle>
);
}
Installation des dépendances
Il est presque temps de tester votre widget, mais nous devons nous occuper de quelques points avant de le faire. Nous devons nous assurer que toutes les bibliothèques que nous avons utilisées sont correctement importées dans notre dossier de widgets. Ouvrez à nouveau votre terminal et saisissez la commande.
npm install --save
Attendez qu'il télécharge et installe toutes les dépendances dont votre code pourrait avoir besoin.
Si quelque chose ne va pas ou si vous devez recommencer, vous pouvez également effectuer une nouvelle installation qui supprime tous les modules de nœuds et les réinstalle avec cette commande. (mais ne le faites que si c'est absolument nécessaire !)
npm ci --save
Création d'un fichier widget .mpk
Pour regrouper votre widget et créer un .mpk qui peut être utilisé dans votre Mendix projet, exécutez la commande suivante dans votre terminal :
npm run build
Cette action va créer le code de votre widget, puis copier le widget dans votre dossier de widgets. La dernière étape consiste à synchroniser votre répertoire d'applications dans Studio Pro, soit en appuyant sur F4, soit en allant dans « Application » → « Synchroniser le répertoire d'applications » dans le menu supérieur de Studio Pro.
Vous pouvez désormais accéder à votre widget lors du développement dans Studio Pro. Le widget devra être placé dans une vue de données pour le contexte et s'attendra à ce qu'un attribut entier lui soit connecté, mais une fois que vous avez configuré cela, vous pouvez exécuter et tester votre nouveau widget à l'aide de l'application Make it Native 9.
En savoir plus sur la création d'un widget enfichable
- https://docs.mendix.com/refguide/getting-the-make-it-native-app
- https://docs.mendix.com/howto/extensibility/create-a-pluggable-widget-one
- https://docs.mendix.com/howto/extensibility/create-a-pluggable-widget-two
- https://academy.mendix.com/link/path/108/Build-a-Pluggable-Widget
- https://docs.mendix.com/apidocs-mxsdk/apidocs/pluggable-widgets
- https://docs.mendix.com/apidocs-mxsdk/apidocs/client-apis-for-pluggable-widgets