Подтвердить что ты не робот

AngularJS ng-model $scope в ng-repeat - undefined

Я заранее извиняюсь, если не буду правильно формулировать это. У меня есть текстовое поле с ng-model внутри ng-repeat, и когда я пытаюсь получить значение текстового поля, оно всегда undefined. Я просто хочу, чтобы он отображал все, что я набираю в соответствующем текстовом поле.

Кажется, проблема с $scope, так как я могу сделать $scope.postText глобальный или на уровне корневого контроллера, чтобы он мог быть доступен?

Здесь JSFiddle поможет разобраться: http://jsfiddle.net/stevenng/9mx9B/14/

4b9b3361

Ответ 1

В выражении click вы можете ссылаться на postText и получить доступ к нему в вашей функции savePost. Если это не было в ng-repeat, вы можете получить доступ к одиночному $scope.postText, но ng-repeat создает новую область для каждого элемента.

Здесь - обновленная скрипка.

<div ng-repeat="post in posts">
   <strong>{{post}}</strong>
   <input type="text" ng-model="postText">
   <a href="#" ng-click="savePost(postText)">save post</a>
</div>

$scope.savePost = function(post){
   alert('post stuff in textbox: ' + post);
}

Ответ 2

Как уже говорилось в @Gloopy, ng-repeat создает новую дочернюю область для каждого элемента в вашем массиве posts. Поскольку каждый элемент массива posts является примитивным (строка), ng-repeat также создает свойство post для каждой дочерней области и назначает каждому из них соответствующее значение из массива. Внутри блока ng-repeat находится ng-model="postText". Это создает свойство postText для каждого из дочерних областей. Вот что это все выглядит (для 2 из 4 дочерних областей):

ng-repeat scopes

Когда пользователь вводит какой-либо текст в одно из текстовых полей ввода, соответствующий серый квадрат сохранит текст. (Например, второй (сверху) серый ящик будет хранить текст, который пользователь вводит в текстовое поле "tech".) Поля родительского объекта не могут видеть свойства postText в области дочерних объектов - это проблема, которая у вас была. Существует три общих решения:

  • @Gloopy answer: определите функцию в родительской области (к которой могут иметь доступ дочерние области, поскольку дочерние области ng-repeat прототипически наследуются от родительской области) и передать значение свойства дочерней области (т.е. значение postText) до родительский.
  • Используйте объекты вместо примитивов в массиве posts. НАПРИМЕР,
    $scope.posts = [ {type: 'tech'}, {type: 'news'}, ...];
    Затем в вашем цикле ng-repeat используйте <input type="text" ng-model="post.postText">
    Поскольку каждый элемент массива является объектом (а не примитивным), каждая дочерняя область получает ссылку на соответствующий объект в массиве posts, а не на копию (значения). Поэтому post.postText создается в родительском объекте $scope posts, и, следовательно, он отображается в родительской области. (Итак, в этом случае дочерние области просто вызывают savePost() - не нужно было бы передавать какие-либо значения до родительской области.)
    Другими словами, если пользователь набрал "это связано с технологией" в первом текстовом поле, массив posts в родительском объекте будет автоматически обновляться следующим образом:
    $scope.posts = [ {type: 'tech', postText: 'this is tech related'}, {type: 'news'}, ...];
    Последнее примечание: свойство postText не добавляется к объекту posts, пока пользователь не наберет что-то.
  • Используйте ng-model="$parent.someProperty", чтобы привязать элемент формы к свойству в родительской области, а не к области дочернего элемента. Это решение будет сложно реализовать для вашего сценария, и это довольно хрупкое решение, так как оно зависит от структуры HTML для наследования области... но я упоминаю его для полноты.

(Четвертое решение было представлено @Renan в комментариях к ответу @Gloopy. Это похоже на решение 1., но с вариацией: this используется вместо передачи значения до родителя. не является поклонником этого подхода, так как это затрудняет определение того, к какой переменной области доступа обращаются или изменяются. Я думаю, что лучше, чтобы функции, определенные в области $scope, только открывали и изменяли свою собственную область $.)

Для получения дополнительной информации (и большего количества изображений) о том, как наследование прототипического объема работает в Angular, см. Каковы нюансы объема прототипа/прототипного наследования в AngularJS?

Ответ 3

Это может быть поздний ответ. Пожалуйста, обратитесь к этой скрипке. http://jsfiddle.net/X5gd2/ Пожалуйста, обратитесь к консоли firebug, когда вы нажимаете на ссылки после ввода некоторых текстов в текстовое поле. Идея состоит в том, чтобы элемент itemcontroller для каждого из представлений повторялся внутри ng-repeat.

Контроллер элемента:

function postItemController($scope){
    $scope.savePost = function(){
        console.log($scope.postText + " which belongs to " + $scope.post +" will be saved")
    }
}

Ответ 4

Разделите модель на заголовок и значение

angular.module('MyApp',[]);

function PostCtrl($scope) {
     $scope.posts = [{heading:'tech',value:''}, {heading:'news',value:''},     {heading:'sports',value:''},{heading:'health',value:''}];

    $scope.savePost = function(post){
        alert( 'post stuff in textbox: ' + post);
    }
}

HTML ниже..

<div ng-app="MyApp">
    <div ng-controller="PostCtrl">
        <div ng-repeat="post in posts">
          <strong>{{post.heading}}</strong>
          <input type="text" ng-model="post.value"> 
          <a href="#" ng-click="savePost(post.value)">save post</a>   
        </div>
    </div>
</div>

Проверьте этот скрипт..