web-dev-qa-db-fra.com

Comment créer une directive avec un modèle dynamique dans AngularJS?

Comment créer une directive avec un modèle dynamique?

'use strict';

app.directive('ngFormField', function($compile) {
return {
    transclude: true,
    scope: {
        label: '@'
    },
    template: '<label for="user_email">{{label}}</label>',
    // append
    replace: true,
    // attribute restriction
    restrict: 'E',
    // linking method
    link: function($scope, element, attrs) {
        switch (attrs['type']) {
            case "text":
                // append input field to "template"
            case "select":
                // append select dropdown to "template"
        }
    }
  }
});
<ng-form-field label="First Name" type="text"></ng-form-field>

C’est ce que j’ai pour l’instant et elle affiche correctement l’étiquette. Cependant, je ne sais pas comment ajouter du code HTML supplémentaire au modèle. Ou en combinant 2 modèles en 1.

29
teepusink

Avait un besoin similaire. $compile fait le travail. (Pas tout à fait sûr que ce soit "LA" façon de le faire, travaillant toujours mon chemin angulaire)

http://jsbin.com/ebuhuv/7/edit - mon test d'exploration.

Une chose à noter (d'après mon exemple), une de mes exigences était que le modèle change en fonction d'un attribut type une fois que vous avez cliqué sur Enregistrer, et que les modèles étaient très différents. Donc, vous obtenez la liaison de données. Si vous avez besoin d’un nouveau modèle, vous devrez le recompiler.

18
nowk

j'ai utilisé le $ templateCache pour accomplir quelque chose de similaire. Je mets plusieurs ng-templates dans un seul fichier html, que je référence en utilisant templateUrl de la directive. qui garantit que le code HTML est disponible pour le cache de modèles. alors je peux simplement sélectionner par id pour obtenir le ng-template que je veux.

template.html:

<script type="text/ng-template" id=“foo”>
foo
</script>

<script type="text/ng-template" id=“bar”>
bar
</script>

directif:

myapp.directive(‘foobardirective’, ['$compile', '$templateCache', function ($compile, $templateCache) {

    var getTemplate = function(data) {
        // use data to determine which template to use
        var templateid = 'foo';
        var template = $templateCache.get(templateid);
        return template;
    }

    return {
        templateUrl: 'views/partials/template.html',
        scope: {data: '='},
        restrict: 'E',
        link: function(scope, element) {
            var template = getTemplate(scope.data);

            element.html(template);
            $compile(element.contents())(scope);
        }
    };
}]);
29
zim

Vous devez déplacer votre commutateur dans le modèle en utilisant la directive ' ng-switch ':

module.directive('testForm', function() {
    return {
        restrict: 'E',
        controllerAs: 'form',
        controller: function ($scope) {
            console.log("Form controller initialization");
            var self = this;
            this.fields = {};
            this.addField = function(field) {
                console.log("New field: ", field);
                self.fields[field.name] = field;
            };
        }
    }
});

module.directive('formField', function () {
    return {
        require: "^testForm",
        template:
            '<div ng-switch="field.fieldType">' +
            '    <span>{{title}}:</span>' +
            '    <input' +
            '        ng-switch-when="text"' +
            '        name="{{field.name}}"' +
            '        type="text"' +
            '        ng-model="field.value"' +
            '    />' +
            '    <select' +
            '        ng-switch-when="select"' +
            '        name="{{field.name}}"' +
            '        ng-model="field.value"' +
            '        ng-options="option for option in options">' +
            '        <option value=""></option>' +
            '    </select>' +
            '</div>',
        restrict: 'E',
        replace: true,
        scope: {
            fieldType: "@",
            title: "@",
            name: "@",
            value: "@",
            options: "=",
        },
        link: function($scope, $element, $attrs, form) {
            $scope.field = $scope;
            form.addField($scope);
        }
    };
});

Il peut être utilisé comme ceci:

<test-form>
    <div>
        User '{{!form.fields.email.value}}' will be a {{!form.fields.role.value}}
    </div>
    <form-field title="Email" name="email" field-type="text" value="[email protected]"></form-field>
    <form-field title="Role" name="role" field-type="select" options="['Cook', 'Eater']"></form-field>
    <form-field title="Sex" name="sex" field-type="select" options="['Awesome', 'So-so', 'awful']"></form-field>
</test-form>
8
Aquajet

Si vous souhaitez utiliser la directive AngularJs avec un modèle dynamique, vous pouvez utiliser ces réponses. Cependant, les syntaxes professional et legal sont plus nombreuses .Vous pouvez utiliser templateUrl non seulement avec une valeur unique.Vous pouvez utilisez-le en tant que fonction, qui renvoie une valeur sous la forme url. Cette fonction possède des arguments que vous pouvez utiliser.

http://www.w3docs.com/snippets/angularjs/dynamically-change-template-url-in-angularjs-directives.html

3
Hazarapet Tunanyan

Une méthode consiste à utiliser une fonction de modèle dans votre directive:

...
template: function(tElem, tAttrs){
    return '<div ng-include="' + tAttrs.template + '" />';
}
...
2
user2173353

J'ai réussi à gérer ce problème. Ci-dessous le lien:

https://github.com/nakosung/ng-dynamic-template-example

avec le fichier spécifique étant:

https://github.com/nakosung/ng-dynamic-template-example/blob/master/src/main.coffee

La directive dynamicTemplate héberge un modèle dynamique qui est passé dans scope et l'élément hébergé agit comme d'autres éléments angulaires natifs.

scope.template = '< div ng-controller="SomeUberCtrl">rocks< /div>'
1
nakosung

Je suis dans la même situation, ma solution complète a été postée ici

Fondamentalement, je charge un modèle dans la directive de cette manière

var tpl = '' + 
    <div ng-if="maxLength" 
        ng-include="\'length.tpl.html\'">
    </div>' +
    '<div ng-if="required" 
        ng-include="\'required.tpl.html\'">
    </div>';

puis, en fonction de la valeur de maxLength et required, je peux charger dynamiquement l'un des 2 modèles, un seul d'entre eux à la fois est affiché si nécessaire.

J'espère que ça aide.

0
felix at housecat