0

私はjsonを生成する角度のあるフォームビルダーに取り組んでいます。1つのことを除いて、すべてが正常に機能します。

ここで例を見つけることができます:http://jsfiddle.net/dJRS5/8/

HTML :

<div ng-app='app'>
    <div class='formBuilderWrapper' id='builderDiv' ng-controller="FormBuilderCtrl" >
        <div class='configArea' data-ng-controller="elementDrag">    
            <h2>drag/drop</h2>
            <form name="form" novalidate class='editBloc'>
                <div data-ng-repeat="field in fields" class='inputEdit'>
                    <data-ng-switch on="field.type">
                        <div class='labelOrder' ng-class='{column : !$last}' drag="$index" dragStyle="columnDrag" drop="$index" dropStyle="columnDrop">{{field.type}}
                        </div>
                        <label for="{{field.name}}" data-ng-bind-html-unsafe="field.caption"></label>

                        <input data-ng-switch-when="Text" type="text" placeholder="{{field.placeholder}}" data-ng-model="field.value" />

                        <p data-ng-switch-when="Text/paragraph" data-ng-model="field.value" data-ng-bind-html-unsafe="field.paragraph"></p>

                            <span data-ng-switch-when="Yes/no question">
                                <p data-ng-bind-html-unsafe="field.yesNoQuestion"></p>
                                <input type='radio' name="yesNoQuestion" id="yesNoQuestion_yes" value="yesNoQuestion_yes" />
                                <label for="yesNoQuestion_yes">Oui</label>
                                <input type='radio' name="yesNoQuestion" id="yesNoQuestion_no" value="yesNoQuestion_no"/>
                                <label for="yesNoQuestion_no">Non</label>
                            </span>     
            <p data-ng-switch-when="Submit button" class='submit' data-ng-model="field.value">
                    <input value="{{field.name}}" type="submit">
                </p>                        
                    </data-ng-switch>
                </div>
            </form>
        </div>        
        <div id='previewArea' data-ng-controller="formWriterCtrl">
            <h2>preview</h2>    
            <div data-ng-repeat="item in fields" content="item" class='templating-html'></div>
        </div>        
    </div>
</div>

JS:

    var app = angular.module('app', []);

    app.controller('FormBuilderCtrl', ['$scope', function ($scope){
        $scope.fields = [{"type":"Text/paragraph","paragraph":"hello1"},{"type":"Yes/no question","yesNoQuestion":"following items must be hidden","yes":"yes","no":"no"},{"type":"Text/paragraph","paragraph":"hello2"},{"type":"Submit button","name":"last item"}]  ;
    }]);


    app.controller('elementDrag', ["$scope", "$rootScope", function($scope, $rootScope, $compile) {
        $rootScope.$on('dropEvent', function(evt, dragged, dropped) {
            if($scope.fields[dropped].type == 'submitButton' || $scope.fields[dragged].type == 'submitButton'){
                return;
            }
            var tempElement = $scope.fields[dragged];
            $scope.fields[dragged] = $scope.fields[dropped];
            $scope.fields[dropped] = tempElement;
            $scope.$apply();
        });
    }]);

    app.directive("drag", ["$rootScope", function($rootScope) {
        function dragStart(evt, element, dragStyle) {
            if(element.hasClass('column')){
                element.addClass(dragStyle);
                evt.dataTransfer.setData("id", evt.target.id);
                evt.dataTransfer.effectAllowed = 'move';
            }
        };
        function dragEnd(evt, element, dragStyle) {
            element.removeClass(dragStyle);
        };
        return {
            restrict: 'A',
            link: function(scope, element, attrs)  {
                if(scope.$last === false){
                    attrs.$set('draggable', 'true');
                    scope.dragStyle = attrs["dragstyle"];
                    element.bind('dragstart', function(evt) {
                        $rootScope.draggedElement = scope[attrs["drag"]];
                        dragStart(evt, element, scope.dragStyle);
                    });
                    element.bind('dragend', function(evt) {
                        dragEnd(evt, element, scope.dragStyle);
                    });
                }
            }
        }
    }]);

    app.directive("drop", ['$rootScope', function($rootScope) {
        function dragEnter(evt, element, dropStyle) {
            element.addClass(dropStyle);
            evt.preventDefault();
        };
        function dragLeave(evt, element, dropStyle) {
            element.removeClass(dropStyle);
        };
        function dragOver(evt) {
            evt.preventDefault();
        };
        function drop(evt, element, dropStyle) {
            evt.preventDefault();
            element.removeClass(dropStyle);
        };
        return {
            restrict: 'A',
            link: function(scope, element, attrs)  {
                if(scope.$last === false){
                    scope.dropStyle = attrs["dropstyle"];
                    element.bind('dragenter', function(evt) {
                        dragEnter(evt, element, scope.dropStyle);
                    });
                    element.bind('dragleave', function(evt) {
                        dragLeave(evt, element, scope.dropStyle);
                    });
                    element.bind('dragover', dragOver);
                    element.bind('drop', function(evt) {
                        drop(evt, element, scope.dropStyle);
                        var dropData = scope[attrs["drop"]];
                        $rootScope.$broadcast('dropEvent', $rootScope.draggedElement, dropData);
                    });
                }
            }
        }
    }]);



    app.controller('formWriterCtrl', ['$scope', function ($scope){

    }]);  


    app.directive('templatingHtml', function ($compile) {
        var previousElement;
        var previousIndex;
        var i=0;
        var inputs = {};

        var paragraphTemplate = '<p data-ng-bind-html-unsafe="content.paragraph"></p>';    
        var noYesQuestionTemplate = '<p data-ng-bind-html-unsafe="content.yesNoQuestion"></p><input id="a__index__yes" type="radio" name="a__index__"><label for="a__index__yes" />{{content.yes}}</label><input id="a__index__no" class="no" type="radio" name="a__index__" /><label for="a__index__no">{{content.no}}</label>';
        var submitTemplate = '<p class="submit"><input value="{{content.name}}" type="submit" /></p>';

        var getTemplate = function(contentType, contentReplace, contentRequired) {
            var template = '';
            switch(contentType) {
                case 'Text/paragraph':
                    template = paragraphTemplate;
                    break;
                case 'Yes/no question':
                    template = noYesQuestionTemplate;
                    break;
            case 'Submit button':
                    template = submitTemplate;
                    break;
            }

            template = template.replace(/__index__/g, i);        
            return template;
        }

        var linker = function(scope, element, attrs) {
            i++;
            elementTemplate = getTemplate(scope.content.type);
            element.html(elementTemplate);
            if(previousElement == 'Yes/no question'){
                element.children().addClass('hidden');
                element.children().addClass('noYes'+previousIndex); 
            }
            if(scope.content.type == 'Yes/no question'){
                previousElement = scope.content.type;
                previousIndex = i; 
            }
            $compile(element.contents())(scope);
        }

        return {
            restrict: "C",
            link: linker,
            scope:{
                content:'='
            }
        };
    });

この例には 2 つの領域があります: - 最初の領域は Json で ngRepeat を実行し、ドラッグ アンド ドロップで項目を並べ替えることができます - 2 番目の領域も ngRepeat を実行します。これは、コンパイル関数を使用するディレクティブによってテンプレート化されたプレビューです。一部の要素は、私が「はい/いいえの質問」と呼んだ後にある場合、非表示になっています

以下は、フォーム ビルダーによって生成された Json の例です。

$scope.fields = 

[{"type":"Text/paragraph","paragraph":"hello1"},{"type":"Yes/no question","yesNoQuestion":"following items must be hidden","yes":"yes","no":"no"},  
 {"type":"Text/paragraph","paragraph":"hello2"},{"type":"Submit button","name":"last item"}]  ;

ページの読み込みに問題がなければ、Hello1 が表示され、Hello2 が非表示になります。

しかし、「はい/いいえの質問」の後に Hello1 をドロップすると、dom 要素は再編成されますが、Hello1 は隠されません。$compile から来ていると思いますが、解決方法がわかりません。

これで私を助けてくれませんか?

ありがとうございました

4

1 に答える 1

1

リンク機能で、そのルールに基づいて要素に「非表示」クラスを設定していることだけがわかりました(はい/いいえの後)。これは、DOM 要素に対して 1 回だけ呼び出されます (最初に作成されたとき)。データ モデルを更新しても、要素は再作成されません。その場で更新されます。このようにしたい場合は、再作成するメカニズムが必要になります。

これを行うには、次の 3 つの方法があります。

  1. リンカー関数で、上記と同じdropEventものをリッスンします。これは思ったよりも効率的で (非常に高速です)、このhiddenクラスを適用するかどうかを再評価できます。

  2. ngIf のようなものを使用するか、コレクション内で文字通り再作成して、要素を強制的に完全に再作成します。これは効率的ではありませんが、さまざまな理由から望ましい場合もあります。

  3. ユースケースが実際にこれほど単純である場合 (これが、実行しようとしているより複雑なものの還元でない場合) は、CSS を使用してこのようなことを行うことができます。のような単純なルール

    .yes-no-question + .text-paragraph { display: none; }
    

    兄弟ターゲットを使用すると、それほど手間をかけずにこれを直接処理できます。これは明らかにできることははるかに限られていますが、必要なものをカバーする場合は最も効率的なオプションです.

于 2014-07-17T14:16:23.190 に答える