IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VueJS Discussion :

Propriété de classe inaccessible depuis une Vue


Sujet :

VueJS

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de mathisdu42
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2013
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2013
    Messages : 168
    Par défaut Propriété de classe inaccessible depuis une Vue
    Bonjour à tous,

    Je m'initie petit à petit à la combinaison VueJS + TypeScript et suis à l'heure actuelle confronté à un souci avec mes propriétés.
    Ce dont j'utilise :
    • TypeScript.
    • Axios.
    • Injecteur (grossièrement c'est pour éviter de créer des instances de classe dans les constructeurs).
    • Linq to TypeScript (https://www.npmjs.com/package/linq-typescript) (étant très familier avec l'environnement C#, j'utilise un package qui me permet de manipuler les collections plus ou moins à la manière linq).


    Dans un premier temps, je dispose d'une méthode async qui a pour but de faire un appel get et de retourner une promesse KeyValue
    Classe : Pays
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        public async GetDico(): Promise<Array<IKeyValue<number, string>>> {
    		const vals: Array<IKeyValue<number, string>> = [];
     
    		return await dataApi.get("pays").then((rep) => {
    			(rep.data as List<Pays>).forEach((x) => {
    				vals.push({key: x.Id, value: x.Libelle});
    			});
     
    			return vals;
    		});
    	}
    ensuite, j'appelle cette méthode dans une seconde classe dont le but est d'injecter les données récupérées dans un Array lorsque la classe est instanciée
    Classe : Profil
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    @Service()
    export default class Profil {
        public Id: number;
        public IdUtilisateur: number;
        public Prenom: string;
        public Nom: string;
        public DateNaissance: Date;
        public IdGenre: number;
        public IdPays: number;
     
        public dicoPays: Array<IKeyValue<number, string>>;
     
        constructor() {
            this.initDicoPays();
        }
     
        public async initDicoPays() {
            return await Injecteur.resolve<Pays>(Pays).GetDicoo()
            .then((rep) => this.dicoPays = rep);
        }
    }
    Les choses vont se compliquer du côté de la vue. Lorsque je vais instancier une nouvelle classe Profil,
    la méthode initDicoPays sera applée puis les données seront stockées dans la prop dicoPays.

    Le problème est que lorsque je log la prop dicoPays depuis la vue, elle apparait "undefined" alors qu'elle n'est pas censé l'être, en revanche,
    lorsque je log mon objet "Profil" toujours depuis la vue, la prop dicoPays apparait bel et bien et avec les données !

    Une idée de ce à quoi ressemble ma vue :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    <script lang="ts">
    import Profil from "@/appConfig/pocos/Profil";
    import { Component, Vue } from "vue-property-decorator";
     
    @Component
    export default class PremiereEtape extends Vue {
    	public profil: Profil = new Profil();
    	public form = this.$form.createForm(this, { name: "premiere_etape" });
     
    	public created() {
    		console.log(this.profil);
    		console.log("DicoPays :", this.profil.dicoPays);
    	}
    }
    </script>
    La boucle v-for

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    <div class="col-md-6">
    	<a-form-item label="Nationalité" has-feedback>
    		<a-select
    			v-decorator="[
    			'select',
    			{ rules: [{ required: true, message: 'Veuillez sélectionner un pays' }] },
    			]"
    			placeholder="Veuillez sélectionner un pays"
    		>
    			<a-select-option v-for="item in profil.dicoPays" :value="item.value" :key="item.key">
    				{{ item.value }}
    			</a-select-option>
    		</a-select>
    	</a-form-item>
    </div>
    Ce que les logs retournent :

    Nom : logs.png
Affichages : 125
Taille : 17,5 Ko

    (La belle faute ahah)

    Cette Vue est un "composant", il est rendu de cette manière depuis une autre vue:

    Vue : Conteneur.vue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <component class="mt-5" :is="steps[current].content"></component>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
            steps: [
                {
                    title: "Infos. principales",
                    content: PremiereEtape, // Lieu du problème (vue)
                },
                {
                    title: "Infos. complémentaires",
                    content: SecondeEtape,
                },
                {
                    title: "Finalisation",
                    content: TroisiemeEtape,
                },
            ],
    J'ai forcément dû louper quelque chose, il me semble bizarre que depuis cette vue il ne soit pas possible d'accéder à ces props..
    Le problème viendrait-il de la manière dont le composant est rendu ?

    J'aussi tenté une autre manière, plutot que de passer par la classe Profil, j'ai ajouté les méthodes directement dans la vue mais
    une boucle infinie se forme avec le dicoPays.

    Voilà, navré pour la longueur de ce post, j'ai voulu être le plus concis possible tout en donnant les bonnes infos. !
    Merci par avance,

    Mathis.

  2. #2
    Membre Expert
    Avatar de gwyohm
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2007
    Messages
    925
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 925
    Par défaut
    Salut,

    Ton souci, c'est que vue ne détecte pas les changement faits sur la propriété dicoPays de ta classe Profil.

    Le fait que ce soit undefined n'est du coup pas surprenant:
    en créant le composant, tu crées une nouvelle instance de Profil (dicoPays est par défaut undefined).
    en créant une instance de Profil, tu vas chercher les pays en asynchrone (c'est pas fini)
    tu entres dans create tu log profil qui est réactif
    tu logs profil.dicoPays qui est toujours undefined car processus asynchrone
    en tant qu'humain, le temps de voir dans la console le premier log, de cliquer dessus, le processus asynchrone est terminé, tu vois profil avec dicoPays renseigné.

    maintenant j'imagine que dans le formulaire rendu, tu ne vois pas les données, je pense qu'il faut que tu crées un computed dicoPays qui renvoie profil.dicoPays

  3. #3
    Membre confirmé Avatar de mathisdu42
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2013
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2013
    Messages : 168
    Par défaut
    Salut,

    merci pour ta réponse !

    Effectivement tu as raison, le log ne risquait pas d'afficher grand chose étant donné que la méthode est async,
    donc par curiosité j'ai ajouté un setTimeout de quelques secondes et là j'ai bien mon tableau rempli (en log) !

    Hélas, même en ajoutant un computed aucune donnée ne ressort... J'ai pensé à ajouter un watch (pas testé) mais je trouve ça
    vachement tricky pour une simple récupération de données dans un select..

    EDIT : En poursuivant mes tests je me suis rendu compte que tout mon formulaire faisait crash le DOM,
    le problème était :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public form = this.$form.createForm(this, { name: "premiere_etape" });
    ,
    j'ai donc réorganisé ma vue de cette manière

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    export default class PremiereEtape extends Vue {
    	public profil: Profil;
    	public form: WrappedFormUtils;
     
    	public get test() {
    		return this.profil.dicoPays;
    	}
     
    	public created() {
    		this.form = this.$form.createForm(this, { name: "premiere_etape" });
    		this.profil = Injecteur.resolve<Profil>(Profil);
    	}
    }
    J'ai désormais bien accès à la propriété "dicoPays" depuis la vue mais aucune réactivité du côté du select.
    Lorsque je fais une modification sur ma vue, que je l'enregistre (VS Code), il y a le "hot reload" et mon select apparait avec les données du dico
    mais dès que je refresh la page, aucune donnée

    CTRL + S côté VS Code :
    Nom : 1.png
Affichages : 107
Taille : 7,2 Ko

    Après le refresh de la page :
    Nom : 2.png
Affichages : 94
Taille : 6,5 Ko

    A noter que j'utilise bien une propriété calculée ...

  4. #4
    Membre confirmé Avatar de mathisdu42
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2013
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2013
    Messages : 168
    Par défaut
    Problème réglé, la bouche v-for allait chercher le dicoPays directement après la création du composant,
    de ce fait, le select était vide puisque les données n'étaient pas encore chargées.

    J'ai donc ajouté un système d'état dans le store avec une propriété "chargement" set à false par défaut.
    Avant l'exécution de la requête, je set la propriété à "true" et à la fin à "false", j'exploite cette donnée dans ma vue
    de cette manière, tant que le chargement est en cours la boucle n'est pas exécutée !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	public get isDataLoaded() {
    		return this.$store.state.utilisateur.chargement;
    	}

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Variable Protected inaccessible depuis une classe héritée
    Par Totanne dans le forum VB.NET
    Réponses: 1
    Dernier message: 14/07/2020, 16h19
  2. Appel d'une classe C# depuis une page ASPX
    Par grafaa dans le forum C#
    Réponses: 4
    Dernier message: 03/07/2009, 18h52
  3. Classe inaccessible depuis un projet Silverlight
    Par cyberbobby dans le forum Windows Communication Foundation
    Réponses: 6
    Dernier message: 25/05/2009, 15h33
  4. Instanciation d'une classe fille depuis une classe mère
    Par khaled-benloucif dans le forum Langage
    Réponses: 2
    Dernier message: 30/01/2009, 23h59
  5. Réponses: 9
    Dernier message: 13/03/2006, 17h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo