programing

지시문 내 템플리트 사용자 정의

jooyons 2023. 3. 1. 10:41
반응형

지시문 내 템플리트 사용자 정의

다음과 같은 Bootstrap의 마크업을 사용하는 폼이 있습니다.

<form class="form-horizontal">
  <fieldset>
    <legend>Legend text</legend>
    <div class="control-group">
      <label class="control-label" for="nameInput">Name</label>
      <div class="controls">
        <input type="text" class="input-xlarge" id="nameInput">
        <p class="help-block">Supporting help text</p>
      </div>
    </div>
  </fieldset>
</form>

여기에 보일러 플레이트 코드가 많이 들어있기 때문에 다음과 같은 새로운 명령어인 폼 입력으로 줄이고 싶습니다.

<form-input label="Name" form-id="nameInput"></form-input>

는 다음을 생성합니다.

   <div class="control-group">
      <label class="control-label" for="nameInput">Name</label>
      <div class="controls">
        <input type="text" class="input-xlarge" id="nameInput">
      </div>
    </div>

간단한 템플릿으로 이 정도 작업을 할 수 있습니다.

angular.module('formComponents', [])
    .directive('formInput', function() {
        return {
            restrict: 'E',
            scope: {
                label: 'bind',
                formId: 'bind'
            },
            template:   '<div class="control-group">' +
                            '<label class="control-label" for="{{formId}}">{{label}}</label>' +
                            '<div class="controls">' +
                                '<input type="text" class="input-xlarge" id="{{formId}}" name="{{formId}}">' +
                            '</div>' +
                        '</div>'

        }
    })

다만, 보다 고도의 기능을 추가하게 되면, 막히게 됩니다.

템플릿에서 기본값을 지원하려면 어떻게 해야 합니까?

지시문에 "type" 매개 변수를 선택적 속성으로 표시하려고 합니다. 예:

<form-input label="Password" form-id="password" type="password"/></form-input>
<form-input label="Email address" form-id="emailAddress" type="email" /></form-input>

단, 아무것도 지정되어 있지 않은 경우 디폴트로"text"어떻게 지원하면 좋을까요?

애트리뷰트의 유무에 따라 템플릿을 커스터마이즈하려면 어떻게 해야 합니까?

또, 「필수」아트리뷰트가 있으면 서포트할 수 있으면 좋겠습니다.예:

<form-input label="Email address" form-id="emailAddress" type="email" required/></form-input>

한다면required지시문에 있습니다. 생성된 명령어에 추가하고 싶습니다.<input />그 이외의 경우에는 무시해 주세요.어떻게 해야 할지 모르겠어요.

이러한 요건이 단순한 템플릿을 넘어 컴파일 전 단계를 사용해야 할 것 같습니다만, 어디서부터 시작해야 할지 막막합니다.

angular.module('formComponents', [])
  .directive('formInput', function() {
    return {
        restrict: 'E',
        compile: function(element, attrs) {
            var type = attrs.type || 'text';
            var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
            var htmlText = '<div class="control-group">' +
                '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                    '<div class="controls">' +
                    '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                    '</div>' +
                '</div>';
            element.replaceWith(htmlText);
        }
    };
})

Misko가 제안한 솔루션을 사용하려고 했지만, 제 상황에서는 템플릿 html에 통합해야 하는 속성 자체가 지시사항이었습니다.

유감스럽게도 결과 템플릿에서 참조되는 모든 지시어가 올바르게 동작하지는 않았습니다.각도 코드를 조사하여 근본 원인을 찾을 시간이 부족했지만 해결 방법을 찾아냈습니다. 이것이 잠재적으로 도움이 될 수 있습니다.

해결책은 템플릿 html을 만드는 코드를 컴파일 함수에서 템플릿 함수로 이동하는 것이었습니다.위의 코드에 근거한 예:

    angular.module('formComponents', [])
  .directive('formInput', function() {
    return {
        restrict: 'E',
        template: function(element, attrs) {
           var type = attrs.type || 'text';
            var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
            var htmlText = '<div class="control-group">' +
                '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                    '<div class="controls">' +
                    '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                    '</div>' +
                '</div>';
             return htmlText;
        }
        compile: function(element, attrs)
        {
           //do whatever else is necessary
        }
    }
})

유감스럽게도 위의 답변은 효과가 없습니다.특히 컴파일 단계에서는 범위에 액세스할 수 없으므로 동적 속성에 따라 필드를 사용자 정의할 수 없습니다.링크 스테이지를 사용하는 것이 가장 유연하다고 생각됩니다(비동기적으로 dom을 작성하는 등).다음의 어프로치는, 다음의 점에 대응하고 있습니다.

<!-- Usage: -->
<form>
  <form-field ng-model="formModel[field.attr]" field="field" ng-repeat="field in fields">
</form>
// directive
angular.module('app')
.directive('formField', function($compile, $parse) {
  return { 
    restrict: 'E', 
    compile: function(element, attrs) {
      var fieldGetter = $parse(attrs.field);

      return function (scope, element, attrs) {
        var template, field, id;
        field = fieldGetter(scope);
        template = '..your dom structure here...'
        element.replaceWith($compile(template)(scope));
      }
    }
  }
})

좀 더 완벽한 코드와 접근법에 대한 기록을 가지고 있는 요지를 만들었습니다.

이게 내가 결국 사용한 것이다.

저는 Angular JS에 익숙하지 않기 때문에 더 나은 대안 솔루션을 보고 싶습니다.

angular.module('formComponents', [])
    .directive('formInput', function() {
        return {
            restrict: 'E',
            scope: {},
            link: function(scope, element, attrs)
            {
                var type = attrs.type || 'text';
                var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
                var htmlText = '<div class="control-group">' +
                    '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                        '<div class="controls">' +
                        '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                        '</div>' +
                    '</div>';
                element.html(htmlText);
            }
        }
    })

사용 예:

<form-input label="Application Name" form-id="appName" required/></form-input>
<form-input type="email" label="Email address" form-id="emailAddress" required/></form-input>
<form-input type="password" label="Password" form-id="password" /></form-input>

언급URL : https://stackoverflow.com/questions/10629238/customizing-the-template-within-a-directive

반응형