Comment obtenir les parties individuelles d'un nombre formaté pour un affichage personnalisé
Décomposez les nombres formatés en composants pour appliquer un style personnalisé et créer des interfaces complexes
Introduction
La méthode format() renvoie une chaîne formatée complète comme "1 234,56 $" ou "1,5 M". Cela fonctionne bien pour un affichage simple, mais vous ne pouvez pas styliser les différentes parties individuellement. Vous ne pouvez pas mettre le symbole monétaire en gras, colorer la partie décimale différemment ou appliquer un balisage personnalisé à des composants spécifiques.
JavaScript fournit la méthode formatToParts() pour résoudre ce problème. Au lieu de renvoyer une seule chaîne, elle renvoie un tableau d'objets, chacun représentant une partie du nombre formaté. Chaque partie possède un type comme currency, integer ou decimal, et une valeur comme $, 1234 ou .. Vous pouvez ensuite traiter ces parties pour appliquer un style personnalisé, créer des mises en page complexes ou intégrer des nombres formatés dans des interfaces utilisateur riches.
Pourquoi les chaînes formatées sont difficiles à personnaliser
Lorsque vous recevez une chaîne formatée comme "1 234,56 $", vous ne pouvez pas facilement identifier où se termine le symbole monétaire et où commence le nombre. Différentes locales placent les symboles à des positions différentes. Certaines locales utilisent des séparateurs différents. Analyser ces chaînes de manière fiable nécessite une logique complexe qui duplique les règles de formatage déjà implémentées dans l'API Intl.
Considérez un tableau de bord qui affiche des montants monétaires avec le symbole monétaire dans une couleur différente. Avec format(), vous devriez :
- Détecter quels caractères constituent le symbole monétaire
- Tenir compte des espaces entre le symbole et le nombre
- Gérer les différentes positions de symbole selon les locales
- Analyser la chaîne avec précaution pour éviter de casser le nombre
Cette approche est fragile et sujette aux erreurs. Toute modification des règles de formatage des paramètres régionaux casse votre logique d'analyse.
La méthode formatToParts() élimine ce problème en fournissant les composants séparément. Vous recevez des données structurées qui vous indiquent exactement quelle partie correspond à quoi, quel que soit le paramètre régional.
Utiliser formatToParts pour obtenir les composants d'un nombre
La méthode formatToParts() fonctionne de manière identique à format() à l'exception de sa valeur de retour. Vous créez un formateur avec les mêmes options, puis appelez formatToParts() au lieu de format().
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
console.log(parts);
Cela produit un tableau d'objets :
[
{ type: "currency", value: "$" },
{ type: "integer", value: "1" },
{ type: "group", value: "," },
{ type: "integer", value: "234" },
{ type: "decimal", value: "." },
{ type: "fraction", value: "56" }
]
Chaque objet contient une propriété type identifiant ce que la partie représente et une propriété value contenant la chaîne réelle. Les parties apparaissent dans le même ordre qu'elles apparaîtraient dans la sortie formatée.
Vous pouvez le vérifier en joignant toutes les valeurs ensemble :
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Output: "$1,234.56"
Les parties concaténées produisent exactement la même sortie que l'appel de format().
Comprendre les types de parties
La propriété type identifie chaque composant. Différentes options de formatage produisent différents types de parties.
Pour le formatage de base des nombres :
const formatter = new Intl.NumberFormat("en-US");
const parts = formatter.formatToParts(1234.56);
console.log(parts);
// [
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
Le type integer représente la partie entière du nombre. Plusieurs parties integer apparaissent lorsque des séparateurs de groupes divisent le nombre. Le type group représente le séparateur de milliers. Le type decimal représente le séparateur décimal. Le type fraction représente les chiffres après la décimale.
Pour le formatage des devises :
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR"
});
const parts = formatter.formatToParts(1234.56);
console.log(parts);
// [
// { type: "currency", value: "€" },
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
Le type currency apparaît avant ou après le nombre selon les conventions du paramètre régional.
Pour les pourcentages :
const formatter = new Intl.NumberFormat("en-US", {
style: "percent"
});
const parts = formatter.formatToParts(0.1234);
console.log(parts);
// [
// { type: "integer", value: "12" },
// { type: "percentSign", value: "%" }
// ]
Le type percentSign représente le symbole de pourcentage.
Pour la notation compacte :
const formatter = new Intl.NumberFormat("en-US", {
notation: "compact"
});
const parts = formatter.formatToParts(1500000);
console.log(parts);
// [
// { type: "integer", value: "1" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "5" },
// { type: "compact", value: "M" }
// ]
Le type compact représente l'indicateur de magnitude comme K, M ou B.
Appliquer un style personnalisé aux parties de nombre
Le cas d'usage principal de formatToParts() est d'appliquer différents styles à différents composants. Vous pouvez traiter le tableau de parties pour envelopper des types spécifiques dans des éléments HTML.
Mettre le symbole monétaire en gras :
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
const html = parts
.map(part => {
if (part.type === "currency") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<strong>$</strong>1,234.56"
Cette approche fonctionne pour tout langage de balisage. Vous pouvez générer du HTML, du JSX ou tout autre format en traitant le tableau de parties.
Styliser différemment les portions décimales :
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2
});
const parts = formatter.formatToParts(1234.5);
const html = parts
.map(part => {
if (part.type === "decimal" || part.type === "fraction") {
return `<span class="text-gray-500">${part.value}</span>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "1,234<span class="text-gray-500">.50</span>"
Ce modèle est courant dans les affichages de prix où la portion décimale apparaît plus petite ou plus claire.
Coder en couleur les nombres négatifs
Les applications financières affichent souvent les nombres négatifs en rouge. Avec formatToParts(), vous pouvez détecter le signe moins et appliquer le style en conséquence.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatWithColor(number) {
const parts = formatter.formatToParts(number);
const hasMinusSign = parts.some(part => part.type === "minusSign");
const html = parts
.map(part => part.value)
.join("");
if (hasMinusSign) {
return `<span class="text-red-600">${html}</span>`;
}
return html;
}
console.log(formatWithColor(-1234.56));
// Output: "<span class="text-red-600">-$1,234.56</span>"
console.log(formatWithColor(1234.56));
// Output: "$1,234.56"
Cette approche détecte les nombres négatifs de manière fiable dans toutes les locales, même celles qui utilisent des symboles ou des positions différents pour les indicateurs négatifs.
Créer des affichages de nombres personnalisés avec plusieurs styles
Les interfaces complexes combinent souvent plusieurs règles de style. Vous pouvez appliquer différentes classes ou éléments à différents types de parties simultanément.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatCurrency(number) {
const parts = formatter.formatToParts(number);
return parts
.map(part => {
switch (part.type) {
case "currency":
return `<span class="currency-symbol">${part.value}</span>`;
case "integer":
return `<span class="integer">${part.value}</span>`;
case "group":
return `<span class="group">${part.value}</span>`;
case "decimal":
return `<span class="decimal">${part.value}</span>`;
case "fraction":
return `<span class="fraction">${part.value}</span>`;
case "minusSign":
return `<span class="minus">${part.value}</span>`;
default:
return part.value;
}
})
.join("");
}
console.log(formatCurrency(1234.56));
// Output: "<span class="currency-symbol">$</span><span class="integer">1</span><span class="group">,</span><span class="integer">234</span><span class="decimal">.</span><span class="fraction">56</span>"
Ce contrôle granulaire permet un style précis pour chaque composant. Vous pouvez ensuite utiliser CSS pour styliser chaque classe différemment.
Tous les types de parties disponibles
La propriété type peut avoir ces valeurs selon les options de formatage utilisées :
integer: chiffres entiersfraction: chiffres décimauxdecimal: séparateur décimalgroup: séparateur de millierscurrency: symbole monétaireliteral: espacement ou autre texte littéral ajouté par le formatagepercentSign: symbole de pourcentageminusSign: indicateur de nombre négatifplusSign: indicateur de nombre positif (lorsquesignDisplayest défini)unit: chaîne d'unité pour le formatage d'unitécompact: indicateur de magnitude en notation compacte (K, M, B)exponentInteger: valeur d'exposant en notation scientifiqueexponentMinusSign: signe négatif dans l'exposantexponentSeparator: symbole séparant la mantisse de l'exposantinfinity: représentation de l'infininan: représentation de non-nombreunknown: jetons non reconnus
Toutes les options de formatage ne produisent pas tous les types de parties. Les parties que vous recevez dépendent de la valeur numérique et de la configuration du formateur.
La notation scientifique produit des parties liées à l'exposant :
const formatter = new Intl.NumberFormat("en-US", {
notation: "scientific"
});
const parts = formatter.formatToParts(1234);
console.log(parts);
// [
// { type: "integer", value: "1" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "234" },
// { type: "exponentSeparator", value: "E" },
// { type: "exponentInteger", value: "3" }
// ]
Les valeurs spéciales produisent des types de parties spécifiques :
const formatter = new Intl.NumberFormat("en-US");
console.log(formatter.formatToParts(Infinity));
// [{ type: "infinity", value: "∞" }]
console.log(formatter.formatToParts(NaN));
// [{ type: "nan", value: "NaN" }]
Créer des affichages de nombres accessibles
Vous pouvez utiliser formatToParts() pour ajouter des attributs d'accessibilité aux nombres formatés. Cela aide les lecteurs d'écran à annoncer correctement les valeurs.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatAccessibleCurrency(number) {
const parts = formatter.formatToParts(number);
const formatted = parts.map(part => part.value).join("");
return `<span aria-label="${number} US dollars">${formatted}</span>`;
}
console.log(formatAccessibleCurrency(1234.56));
// Output: "<span aria-label="1234.56 US dollars">$1,234.56</span>"
Cela garantit que les lecteurs d'écran annoncent à la fois la valeur d'affichage formatée et la valeur numérique sous-jacente avec le contexte approprié.
Mettre en évidence des plages de nombres spécifiques
Certaines applications mettent en évidence les nombres qui se situent dans certaines plages. Avec formatToParts(), vous pouvez appliquer un style basé sur la valeur tout en maintenant un formatage approprié.
const formatter = new Intl.NumberFormat("en-US");
function formatWithThreshold(number, threshold) {
const parts = formatter.formatToParts(number);
const formatted = parts.map(part => part.value).join("");
if (number >= threshold) {
return `<span class="text-green-600 font-bold">${formatted}</span>`;
}
return formatted;
}
console.log(formatWithThreshold(1500, 1000));
// Output: "<span class="text-green-600 font-bold">1,500</span>"
console.log(formatWithThreshold(500, 1000));
// Output: "500"
Le nombre reçoit un formatage approprié pour la locale tandis que le style conditionnel s'applique en fonction de la logique métier.
Quand utiliser formatToParts plutôt que format
Utilisez format() lorsque vous avez besoin d'une simple chaîne formatée sans aucune personnalisation. C'est le cas courant pour la plupart des affichages de nombres.
Utilisez formatToParts() lorsque vous devez :
- Appliquer différents styles à différentes parties du nombre
- Construire du HTML ou du JSX avec des nombres formatés
- Ajouter des attributs ou des métadonnées à des composants spécifiques
- Intégrer des nombres formatés dans des mises en page complexes
- Traiter la sortie formatée de manière programmatique
La méthode formatToParts() a un léger surcoût par rapport à format() car elle crée un tableau d'objets au lieu d'une seule chaîne. Cette différence est négligeable pour les applications typiques, mais si vous formatez des milliers de nombres par seconde, format() offre de meilleures performances.
Pour la plupart des applications, choisissez en fonction de vos besoins de style plutôt que des préoccupations de performance. Si vous n'avez pas besoin de personnaliser la sortie, utilisez format(). Si vous avez besoin d'un style ou d'un balisage personnalisé, utilisez formatToParts().
Comment les parties préservent le formatage spécifique à la locale
Le tableau de parties maintient automatiquement les règles de formatage spécifiques à la locale. Différentes locales placent les symboles à différentes positions et utilisent différents séparateurs, mais formatToParts() gère ces différences.
const usdFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
console.log(usdFormatter.formatToParts(1234.56));
// [
// { type: "currency", value: "$" },
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
const eurFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR"
});
console.log(eurFormatter.formatToParts(1234.56));
// [
// { type: "integer", value: "1" },
// { type: "group", value: "." },
// { type: "integer", value: "234" },
// { type: "decimal", value: "," },
// { type: "fraction", value: "56" },
// { type: "literal", value: " " },
// { type: "currency", value: "€" }
// ]
Le formatage allemand place la devise après le nombre avec un espace. Le séparateur de groupe est un point et le séparateur décimal est une virgule. Votre code de style traite le tableau de parties de la même manière quelle que soit la locale, et le formatage s'adapte automatiquement.
Le type literal représente tout espacement ou texte inséré par le formateur qui ne correspond pas aux autres catégories. Dans le formatage de devise allemand, il représente l'espace entre le nombre et le symbole de devise.
Combiner formatToParts avec des composants de framework
Les frameworks modernes comme React peuvent utiliser formatToParts() pour construire des composants efficacement.
function CurrencyDisplay({ value, locale, currency }) {
const formatter = new Intl.NumberFormat(locale, {
style: "currency",
currency: currency
});
const parts = formatter.formatToParts(value);
return (
<span className="currency-display">
{parts.map((part, index) => {
if (part.type === "currency") {
return <strong key={index}>{part.value}</strong>;
}
if (part.type === "fraction" || part.type === "decimal") {
return <span key={index} className="text-sm text-gray-500">{part.value}</span>;
}
return <span key={index}>{part.value}</span>;
})}
</span>
);
}
Ce composant applique différents styles à différentes parties tout en maintenant un formatage approprié pour toute locale et devise.