2013-03-08 50 views
11

Tôi muốn vẽ lại một hình thức, dựa trên một cấu hình lĩnh vực năng động:Làm cách nào để sử dụng Góc để tạo các trường biểu mẫu động?

$scope.fields = [ 
    { title: 'Label 1', type: 'text', value: 'value1'}, 
    { title: 'Label 2', type: 'textarea', value: 'value2'} 
]; 

này nên đầu ra cái gì đó hoạt động như:

<div> 
    <label>{{field.title}}<br /> 
     <input type="text" ng-model="field.value"/> 
    </label> 
</div> 
<div> 
    <label>{{field.title}}<br /> 
     <textarea ng-model="field.value" rows="5" cols="50"></textarea> 
    </label> 
</div> 

Việc thực hiện đơn giản sẽ được sử dụng if báo cáo để render mẫu cho từng loại trường. Tuy nhiên, vì Angular không hỗ trợ các câu lệnh if, tôi dẫn đến chỉ thị của chỉ thị. Vấn đề của tôi là hiểu cách thức hoạt động của ràng buộc dữ liệu. Các documentation for directives là một chút dày đặc và lý thuyết.

Tôi đã chế nhạo lên một xương trần ví dụ về những gì tôi cố gắng làm ở đây: http://jsfiddle.net/gunnarlium/aj8G3/4/

Vấn đề là các trường mẫu không bị ràng buộc với mô hình, do đó $ scope.fields trong trình () không được cập nhật. Tôi nghi ngờ nội dung của chức năng chỉ thị của tôi là hoàn toàn sai lầm ... :)

Trong tương lai, tôi cũng cần phải hỗ trợ kiểu trường khác, như nút radio, hộp kiểm tra, lựa chọn, vv

+0

Bản sao có thể có của [AngularJS: không thể thay đổi loại đầu vào] (http://stackoverflow.com/questions/15148456/angularjs-cant-change-input-type) – Aides

Trả lời

22

Vấn đề đầu tiên bạn đang chạy vào bất kể chỉ thị bạn đang cố tạo là sử dụng ng-repeat trong một biểu mẫu với các phần tử biểu mẫu. Nó có thể được khôn lanh làm thế nào để ng-lặp lại tạo ra một phạm vi mới.

This directive creates new scope.

tôi cũng khuyên bạn nên thay vì sử dụng element.html mà bạn sử dụng ngSwitch thay vì trong một mẫu phần.

<div class="form-row" data-ng-switch on="field.type"> 
    <div data-ng-switch-when="text"> 
     {{ field.title }}: <input type="text" data-ng-model="field.value" /> 
    </div> 
    <div data-ng-switch-when="textarea"> 
     {{ field.title }}: <textarea data-ng-model="field.value"></textarea> 
    </div> 
</div> 

này vẫn để lại cho bạn với vấn đề thay đổi các yếu tố hình thức trong phạm vi con do ng-repeat và cho rằng tôi khuyên bạn nên sử dụng phương pháp ngChange trên từng yếu tố để thiết lập giá trị khi một mục đã thay đổi. Đây là một trong số ít những thứ mà tôi không nghĩ rằng AngularJS xử lý rất tốt vào lúc này.

+0

Thực ra, ngSwitch chính xác là những gì tôi cần. Không gặp vấn đề phạm vi nào :) (chưa). Tôi vẫn không hiểu rõ các chỉ thị, nhưng đó là một nhiệm vụ cho một ngày khác .. –

+0

@GunnarLium Bạn có thể giải quyết vấn đề này không? Tôi đang cố gắng triển khai một giải pháp tương tự nhưng bị kẹt vì các vấn đề chính xác tương tự ..Tự hỏi liệu bạn có thể chia sẻ thông tin chi tiết của mình nếu/cách bạn giải quyết vấn đề – user6123723

4

Bạn có thể xem xét Metawidget cho việc này. Nó sử dụng lược đồ JSON, nhưng rất khác với trường hợp sử dụng của bạn. Toàn bộ mẫu:

<html ng-app="myApp"> 
    <head> 
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js" type="text/javascript"></script> 
     <script src="http://metawidget.org/js/3.5/metawidget-core.min.js" type="text/javascript"></script> 
     <script src="http://metawidget.org/js/3.5/metawidget-angular.min.js" type="text/javascript"></script> 
     <script type="text/javascript"> 
      angular.module('myApp', [ 'metawidget' ]) 
       .controller('myController', function($scope) { 

        $scope.metawidgetConfig = { 
         inspector: function() { 
          return { 
           properties: { 
            label1: { 
             type: 'string' 
            }, 
            label2: { 
             type: 'string', 
             large: true 
            } 
           } 
          } 
         } 
        } 

        $scope.saveTo = { 
         label1: 'value1', 
         label2: 'value2' 
        } 

        $scope.save = function() { 
         console.log($scope.saveTo); 
        } 
       }); 
     </script> 
    </head> 
    <body ng-controller="myController"> 
     <metawidget ng-model="saveTo" config="metawidgetConfig"> 
     </metawidget> 
     <button ng-click="save()">Save</button> 
    </body> 
</html> 
0

Thuộc tính type có thể được thay đổi khi yếu tố nằm ngoài DOM, vậy tại sao không phải là một chỉ thị nhỏ mà loại bỏ nó từ DOM, những thay đổi đó gõ và sau đó thêm trở lại cùng một chỗ?

$watch là tùy chọn, vì mục tiêu có thể thay đổi động một lần và không tiếp tục thay đổi.

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

 
app.controller('MainCtrl', function($scope) { 
 
    $scope.rangeType = 'range'; 
 
    $scope.newType = 'date' 
 
}); 
 

 
app.directive('dynamicInput', function(){ 
 
    return { 
 
     restrict: "A", 
 
     link: linkFunction 
 
    }; 
 
    
 
    function linkFunction($scope, $element, $attrs){ 
 
     
 
     if($attrs.watch){ 
 
     $scope.$watch(function(){ return $attrs.dynamicInput; }, function(newValue){ 
 
      changeType(newValue); 
 
     }) 
 
     } 
 
     else 
 
     changeType($attrs.dynamicInput); 
 
     
 
     
 
     function changeType(type){ 
 
     var prev = $element[0].previousSibling; 
 
     var parent = $element.parent(); 
 
     $element.remove().attr('type', type); 
 
     if(prev) 
 
      angular.element(prev).after($element); 
 
     else 
 
      parent.append($element); 
 
     } 
 
    } 
 
});
span { 
 
font-size: .7em; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<div ng-app="app" ng-controller="MainCtrl"> 
 
    <h2>Watching Type Change</h2> 
 
    Enter Type: <input ng-model="newType" /><br/> 
 
    Using Type (with siblings): <span>Before</span><input dynamic-input="{{newType}}" watch="true" /><span>After</span><Br> 
 
    Using Type (without siblings): <div><input dynamic-input="{{newType}}" watch="true" /></div> 
 
    
 
    <br/><br/><br/> 
 
    <h2>Without Watch</h3> 
 
    Checkbox: <input dynamic-input="checkbox" /><br /> 
 
    Password: <input dynamic-input="{{ 'password' }}" value="password"/><br /> 
 
    Radio: <input dynamic-input="radio" /><br/> 
 
    Range: <input dynamic-input="{{ rangeType }}" /> 
 
</div>

Tested trong Chrome mới nhất và IE11.

Các vấn đề liên quan