기본값에서 각도 JS 초기화 모델


126

데이터베이스에서 값을로드 한 양식이 있다고 가정하십시오. ng-model을 어떻게 초기화합니까?

예:

<input name="card[description]" ng-model="card.description" value="Visa-4242">

내 컨트롤러에서 $ scope.card는 처음에 정의되어 있지 않습니다. 이와 같은 일 외에 다른 방법이 있습니까?

$scope.card = {
  description: $('myinput').val()
}

답변:


136

이것은 새로운 Angular 응용 프로그램에서 흔히 발생하는 실수입니다. 피할 수 있다면 서버의 HTML에 값을 쓰지 않으려 고합니다. 사실, 서버가 HTML을 완전히 렌더링하는 것을 피할 수 있다면 더 좋습니다.

이상적으로는 Angular HTML 템플릿을 전송 한 다음 JSON에서 $ http를 통해 값을 가져 와서 범위에 넣기를 원합니다.

따라서 가능한 경우 다음을 수행하십시오.

app.controller('MyController', function($scope, $http) {
    $http.get('/getCardInfo.php', function(data) {
       $scope.card = data;
    });
});

<input type="text" ng-model="card.description" />

서버에서 HTML로 값을 절대적으로 렌더링 해야하는 경우 전역 변수에 값을 넣고 $ window를 사용하여 값에 액세스 할 수 있습니다.

페이지 헤더에 다음과 같이 작성하십시오.

<head>
   <script>
       window.card = { description: 'foo' };
   </script>
</head>

그런 다음 컨트롤러에서 다음과 같이 얻을 수 있습니다.

app.controller('MyController', function($scope, $window) {
   $scope.card = $window.card;
});

도움이 되길 바랍니다.


4
예, 도움이됩니다. 나는 Angular 사람들 이이 결정을 내렸다는 사실에 충격을 받았다고 생각합니다.
Calvin Froedge

125
충격을받지 마십시오 ... HTML 렌더링이 서버와 브라우저에서 이동하고 있습니다. 요즘 JavaScript에는 수십 개의 MVC 프레임 워크가 있으며 서버에서 JSON / XML 데이터를 JavaScript 앱으로 호스팅하는 것이 서버의 모든 단일 페이지를 렌더링하는 것보다 훨씬 효율적입니다. 서버가 적중하지 않고 클라이언트 시스템에 많은 작업을 상쇄합니다. 말할 것도없이 대역폭을 절약 할 수 있습니다. 무엇보다도, 동일한 JSON over HTTP를 사용하는 기본 모바일 앱 (또는 실제로 무엇이든)을 가질 수 있습니다. 이것은 미래입니다.
Ben Lesh

3
@blesh : 좋은 대답입니다. 고마워 나는 이것이 앞으로 나아가고이 접근법을 스스로 채택하기 시작했다는 것에 동의한다. 이 주장을 뒷받침하는 링크가 있습니까? 또한 HTML 렌더링을 서버에서 클라이언트로 옮기면 페이지로드 시간이 느려질 수 있습니다. 특히 탐색 트리와 같이 많은 HTML을 렌더링 할 수있는 모바일 장치에서는 더욱 그렇습니다.
GFoley83

19
나는 이것이 '실수'라는 것에 동의하지 않습니다. 경우에 따라 클라이언트 쪽 렌더링이 최상의 솔루션입니다. 다른 경우에는 서버 측 렌더링이 좋습니다. 두 방법 모두 각도를 사용할 수 있으며 클라이언트 측 렌더링은 "각도"로 유지되어서는 안됩니다. 각도는 그보다 더 유연합니다.
hunterloftis은 (는)

8
@blesh, 확실히-SEO가 중요하지만 크롤러의 대체 콘텐츠 비용이 내장 데이터로 각도를 구현하는 비용보다 높습니다-인식 된 속도 또는 렌더링 시간에 매우 높은 가치를 부여하는 모든 응용 프로그램 사용자 경험-많은 콘텐츠 사이트와 전자 상거래 사이트가이 범주 중 하나에 속합니다. 더 나은 사용자 경험을 제공하기 위해 서버에 다음 이동 다시 렌더링 클라이언트 시도 트위터에서 엔지니어가 아니라 자신의 이유를 설명했다 : blog.twitter.com/2012/improving-performance-twittercom은
hunterloftis

236

@blesh가 제안한 작업을 수행하기 위해 앱을 재 작업 할 수없는 경우 ($ http 또는 $ resource로 JSON 데이터를 가져오고 $ scope를 입력) 대신 ng-init 를 사용할 수 있습니다 .

<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">

참조 AngularJS와를 - NG 모델이 사용될 때 입력 텍스트 상자에 값 속성이 무시됩니다?


각도가 낮은 경우 +1 (더 덜 선호하는 방법) 예 : jsfiddle.net/9ymB3
John Lehmann

2
C # 웹 양식과 함께 Angular를 사용하고 ng-init있으며 코드 숨김 / 포스트 백 Eg에서 값을 설정할 때 사용 이 매우 유용하다는 것을 알았습니다 <input name="phone" data-ng-model="frm.phone" data-ng-init="frm.phone= '<%: Model.Phone %>'" data-ng-pattern="/^[0-9() \-+]+$/" type="tel" required />. 못 생겼어? 예, 그러나 트릭을 수행하고 프로세스의 통합 두통을 해결합니다.
GFoley83

13
+1, 우아합니다! 사람들은 신속하고 빠른 행동을 옹호하지만 SO의 많은 사람들은 "모든 클라이언트 측에서 수행"이라고 말합니다. 수백만 개의 HTTP 호출과 같이 스냅 사이트에도 좋습니다. 데이터 서버 측을 템플릿으로 시드하면 캐싱 전략이 가능합니다. Memcached의 정적 또는 동적 / 부분. 이것이 트위터가하는 일입니다. 때로는 유용하지만 다른 경우에는 유용하지 않습니다. 그것을 강조하고 싶었다. @Mark, 당신이 달리 말한 것이 아니라 추가해야했습니다.
oma

1
사실 난 그 뒤로을이 나를 위해 잘 작동, 최고 : stackoverflow.com/a/20522955/329367
대런

1
FWIW : 테스트 할 수 없기 때문에 템플릿 표현식에서 변수 할당을 싫어합니다.
Ben Lesh

60

이것은 분명히 부족하지만 AngularJS에 대한 수정이 쉽게 추가되었습니다. 입력 필드에서 모델 값을 설정하는 간단한 지시문을 작성하십시오.

<input name="card[description]" value="Visa-4242" ng-model="card.description" ng-initial>

내 버전은 다음과 같습니다.

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

app.directive('ngInitial', function() {
  return {
    restrict: 'A',
    controller: [
      '$scope', '$element', '$attrs', '$parse', function($scope, $element, $attrs, $parse) {
        var getter, setter, val;
        val = $attrs.ngInitial || $attrs.value;
        getter = $parse($attrs.ngModel);
        setter = getter.assign;
        setter($scope, val);
      }
    ]
  };
});

좋은 빠른 지시. 대부분의 사람들이 기대하는 것처럼 value =와 ng-model =이 함께 작동 할 수 있도록 이것을 ng-model에 패키지하지 않는 좋은 이유는 무엇입니까?
hunterloftis은 (는)

꽤 좋은! 유용합니다.
santiagobasulto

3
좋은 답변입니다! 난 그냥뿐만 아니라 텍스트 영역이 또한 작업을 만들 수있는 "수정"을 추가 - gist.github.com/rmontgomery429/6191275
라이언 몽고메리을

controller지시어에 대해 정의 했으며 왜 link메소드를 사용하지 않았 습니까? 나는 AngularJS와에 안돼서
칼릴 ebram

1
val = $attrs.ngInitial || $attrs.value || $element.val()선택 요소와 함께 작동 하도록 변경해야 했습니다.
fjsj 2009 년

12

IMHO의 가장 좋은 솔루션은 @Kevin Stone 지시문이지만 모든 조건 (fe select, textarea)에서 작동하도록 업그레이드해야 했으며이 것이 확실하게 작동합니다.

    angular.module('app').directive('ngInitial', function($parse) {
        return {
            restrict: "A",
            compile: function($element, $attrs) {
                var initialValue = $attrs.value || $element.val();
                return {
                    pre: function($scope, $element, $attrs) {
                        $parse($attrs.ngModel).assign($scope, initialValue);
                    }
                }
            }
        }
    });

그리고 select는 어떻습니까?
jwize

7

텍스트 영역, 선택, 라디오 및 확인란을 지원하는 사용자 지정 지시문을 사용할 수 있습니다.이 블로그 게시물 https://glaucocustodio.github.io/2014/10/20/init-ng-model-from-form- fields-attributes / .


1
이것은 좋은 게시물입니다. 질문 이후 가장 좋아하는 대답은 이니셜 값에 따라 입력 값을 설정하는 것이 었습니다.
RPDeshaies

이 코드를 테스트하기 위해 Plnkr를 생성하고 그것을 잘 작동합니다 : plnkr.co/edit/ZTFOAc2ZGIZr6HjsB5gH?p=preview
RPDeshaies

6

HTML 코드 내에서도 사용할 수 있습니다. ng-init="card.description = 12345"

Angular는 권장하지 않으며 위에서 언급했듯이 컨트롤러를 독점적으로 사용해야합니다.

그러나 작동합니다 :)


4

양식에 무거운 유효성 검사와 마스크가 있기 때문에 간단한 접근 방식이 있습니다. 그래서 jquery를 사용하여 내 가치를 다시 얻고 이벤트 "change"를 유효성 검사로 시작합니다.

$('#myidelement').val('123');
$('#myidelement').trigger( "change");

3

다른 사람들이 지적했듯이 뷰에서 데이터를 초기화하는 것은 좋지 않습니다. 그러나 컨트롤러에서 데이터를 초기화하는 것이 좋습니다. ( http://docs.angularjs.org/guide/controller 참조 )

그래서 당신은 쓸 수 있습니다

<input name="card[description]" ng-model="card.description">

$scope.card = { description: 'Visa-4242' };

$http.get('/getCardInfo.php', function(data) {
   $scope.card = data;
});

이렇게하면 뷰에 데이터가 포함되지 않으며 실제 값이로드되는 동안 컨트롤러가 값을 초기화합니다.


3

https://stackoverflow.com/a/17823590/584761 위의 Kevin Stone의 접근 방식을 좋아하는 경우 'input'과 같은 특정 태그에 대한 지시문을 작성하여 더 쉬운 접근 방법을 고려 하십시오 .

app.directive('input', function ($parse) {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, element, attrs) {
            if (attrs.ngModel) {
                val = attrs.value || element.text();
                $parse(attrs.ngModel).assign(scope, val);
            }
        }
    }; });

이 경로를 사용하면 모든 태그에 ng-initial을 추가하는 것에 대해 걱정할 필요가 없습니다. 모델의 값을 태그의 value 속성으로 자동 설정합니다. value 속성을 설정하지 않으면 기본적으로 빈 문자열이됩니다.


3

서버 중심 접근 방식은 다음과 같습니다.

<html ng-app="project">
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script>
        // Create your module
        var dependencies = [];
        var app = angular.module('project', dependencies);

        // Create a 'defaults' service
        app.value("defaults", /* your server-side JSON here */);

        // Create a controller that uses the service
        app.controller('PageController', function(defaults, $scope) {
            // Populate your model with the service
            $scope.card = defaults;
        });
    </script>

    <body>
        <div ng-controller="PageController">
            <!-- Bind with the standard ng-model approach -->
            <input type="text" ng-model="card.description">
        </div>
    </body>
</html>

$ provide.value 가 기본값을 포함하는 서비스를 등록 한다는 점을 제외하면이 질문에 대해 가장 많이 사용되는 답변과 동일한 기본 아이디어 입니다.

따라서 서버에서 다음과 같은 것을 가질 수 있습니다.

{
    description: "Visa-4242"
}

선택한 서버 측 기술을 통해 페이지에 넣습니다. 요점은 다음과 같습니다. https://gist.github.com/exclsr/c8c391d16319b2d31a43


1
내가 알 수있는 한, 이것은 초기 $ http 요청을하는 것이 옵션이 아닌 경우 문제를 처리하는 가장 Angular 방법입니다. 또한 나중에 $ http로 바꾸려면 수정하기가 훨씬 쉽다는 장점도 있습니다. 한 가지 가능한 개선 사항은보다 쉽게 ​​전환 할 수 있도록 약속을 반환하는 것입니다. 전역 변수를 설정하거나 ng-initial을 사용하지 않는 것이 좋습니다.
richard

1

이것은 위에서 언급 한 아이디어의보다 일반적인 버전입니다 ... 모델에 값이 있는지 여부를 확인하고 그렇지 않은 경우 값을 모델로 설정합니다.

JS :

function defaultValueDirective() {
    return {
        restrict: 'A',
        controller: [
            '$scope', '$attrs', '$parse',
            function ($scope, $attrs, $parse) {
                var getter = $parse($attrs.ngModel);
                var setter = getter.assign;
                var value = getter();
                if (value === undefined || value === null) {
                    var defaultValueGetter = $parse($attrs.defaultValue);
                    setter($scope, defaultValueGetter());
                }
            }
        ]
    }
}

HTML (사용 예) :

<select class="form-control"
        ng-options="v for (i, v) in compressionMethods"
        ng-model="action.parameters.Method"
        default-value="'LZMA2'"></select>

이것은 나를 위해 일했지만 $scope호출에 통과 한 후에 만 getter()-이 작업을 시도하는 다른 사람에게 문제가 해결되기를 바랍니다.
zesda

0

@Mark Rajcok이 제안한 것을 시도했습니다. 문자열 값 (Visa-4242)에서 작동합니다. 이 바이올린을 참조하십시오 .

바이올린에서 :

바이올린에서 수행되는 것과 동일한 작업을 ng-repeat모두 사용할 수 있습니다 . 그러나 @Mark Rajcok가 제공 한 답변을 읽은 후에는 프로필 배열이있는 양식에 대해 동일하게 시도하고 싶었습니다. $ scope.profiles = [{}, {}]가 될 때까지 상황이 잘 작동합니다. 컨트롤러의 코드. 이 코드를 제거하면 오류가 발생합니다. 그러나 일반적인 시나리오 $scope.profiles = [{},{}]; 에서는 서버에서 HTML을 인쇄하거나 반향으로 인쇄 할 수 없습니다. @Mark Rajcok이 <input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">서버에서 JavaScript 부분을 에코하지 않고 와 같은 문자열 값에 대해 수행 한 것과 유사한 방식으로 위의 코드를 실행할 수 있습니까 ?


1
ng-init를 사용하여 배열을 초기화 한 다음 ng-repeat를 사용하여 양식 행을 출력 할 수 있습니다. jsfiddle.net/6tP6x/1
Karen Zilles

0

Ryan Montgomery "fix"에 select 요소에 대한 지원 추가

<select class="input-control" ng-model="regCompModel.numberOfEmployeeId" ng-initial>
    <option value="1af38656-a752-4a98-a827-004a0767a52d"> More than 500</option>
    <option value="233a2783-db42-4fdb-b191-0f97d2d9fd43"> Between 250 and 500</option>
    <option value="2bab0669-550c-4555-ae9f-1fdafdb872e5"> Between 100 and 250</option>
    <option value="d471e43b-196c-46e0-9b32-21e24e5469b4"> Between 50 and 100</option>
    <option value="ccdad63f-69be-449f-8b2c-25f844dd19c1"> Between 20 and 50</option>
    <option value="e00637a2-e3e8-4883-9e11-94e58af6e4b7" selected> Less then 20</option>
</select>

app.directive('ngInitial', function () {
return {
    restrict: 'A',
    controller: ['$scope', '$element', '$attrs', '$parse', function ($scope, $element, $attrs, $parse) {
        val = $attrs.sbInitial || $attrs.value || $element.val() || $element.text()
        getter = $parse($attrs.ngModel)
        setter = getter.assign
        setter($scope, val)
    }]
}

});


0

와 같은 URL에 init 값이있는 mypage/id경우 각도 JS의 컨트롤러 location.pathname에서 ID를 찾고 원하는 모델에 할당하는 데 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.