использование элемента в ng-repeat для ng-модели элемента select, когда объекты находятся в разных областях?

У меня есть объект:

$scope.recipe = 
  {
  ...,
  "ingredients": [
    {
      "foodItem": "Cabbage",
      "condition": "Chopped",
      "amount": "3 cups"
    },
    {
      "foodItem": "Carrot",
      "condition": "Grated",
      "amount": ".5 cups"
    },
    {
      "foodItem": "Rice Wine Vinegar",
      "condition": "",
      "amount": ".25 cups"
    },
    {
      "foodItem": "Sesame Seed Oil",
      "condition": "",
      "amount": "3 tablespoons"
    }
  ],
  ...
}

Я использую ng-repeat для создания раскрывающегося списка выбрать для каждого ингредиента в объекте выше (или любой рецепт я выбираю).

У меня есть другой объект:

$scope.foods = 
[
  {
    "name": "Baking Powder",
    "_id": "pJ7ERDIbL9QTDRPn"
  },
  {
    "name": "Beef",
    "_id": "e9HWiXFflHTuwHHP"
  },
  {
    "name": "Bread",
    "_id": "2fFCSMJRYURINLrE"
  },
  {
    "name": "Butter",
    "_id": "SiSryQYOkvUDoxix"
  },
...
]

Что я буду использовать для опций для каждого из выпадающих списков, которые создаются с ng-repeat. Я хочу использовать каждый из foodItems в рецепте в качестве выбора по умолчанию в каждом из отборных выпадающих списков (используя ng-модель). Основываясь на других сообщениях SO, которые я читал, это, кажется, работает с входным элементом, использующим ng-модель в ng-repeat, но не с select, использующим ng-модель с ng-option в ng-repeat. Есть ли способ сделать это с помощью select?

формат html:

<!-- TODO Add a directive to this div element so that it repeats 
    for each recipe ingredient to display. -->
  <div class="ingredient-row" ng-repeat="item in recipe.ingredients">
    <div class="prefix-20 grid-30">
      <p>
        <!-- TODO Add directives to this select element to bind its value 
          to the recipe ingredient model's `foodItem` property and to 
          populate the list with the food items from the database. -->
        <select ng-model="item.foodItem" ng-options="food.name for food in foods">
          <option value="">Select Item</option>
        </select>
      </p>
    </div>
    <div class="grid-30">
      <p>
        <!-- TODO Add a directive to this input element to bind its value 
          to the recipe ingredient model's `condition` property. -->
        <input type="text" value="{{item.condition}}">
      </p>
    </div>
    <div class="grid-15">
      <p>
        <!-- TODO Add a directive to this input element to bind its value 
          to the recipe ingredient model's `amount` property. -->
        <input type="text" value="{{item.amount}}">
      </p>
    </div>
    <div class="grid-5 pad-top">
      <p class="flush-right">
        <!-- TODO Add a directive to this anchor element so that you can 
          delete the recipe ingredient when the user clicks on the 'Delete' link. -->
        <a class="no-action-link"> <img src="images/delete.svg" height="12px"> </a>
      </p>
    </div>
  </div>

Контроллер:

.controller('RecipeDetailController', function($scope,dataService,$location) {

    const init = () => {
      let id = $location.path();
      id = id.slice(6);
      let category;
      console.log(id);

      dataService.getID(id,function(response) {
        $scope.recipe = response.data;
        $scope.title = response.data.name || 'Add New Recipe.';
        category = response.data.category;
      });

      dataService.getAllCategories(function (response) {
        $scope.categories = response.data;
        let index = response.data.findIndex(item => item.name === category);
        if (index === -1) {
          $scope.initial = {"name": "Choose a Category"};
        } else {
          $scope.initial = $scope.categories[index];
        }
      });

      dataService.getAllFoodItems(function (response) {
        $scope.foods = response.data;
      });
    }

    $scope.addIngredient = () => {
//      console.log($scope.recipe);
      let ingredient = '';
      $scope.recipe.ingredients.push('');
    };

    $scope.ingredientDetails = function(ingredient) {
      if (ingredient === null) {
        $scope.condition = '';
        $scope.amount = '';
      } else {
        $scope.condition = ingredient.condition;
        $scope.amount = ingredient.amount;
      }
    };

    $scope.cancelChanges = () => {
      $location.path('/');
    }

    init();

  });

1 ответ

  1. Я создал упрощенный plunker вашего HTML, и воссоздал ваш сценарий, используя статические данные (и изменяя данные так, чтобы значения в $scope.recipe.ingredientsсоответствовали тому, что находится в $scope.foods).

    В вашем случае ng-optionsформа, которую вы используете, все еще пытается назначить значение как объект, а не как строку. Это заканчивается созданием выходного HTML как:

    <option label="Cabbage" value="object:8">Cabbage</option>
    

    Путем изменять ng-optionsнемножко, мы можем получить пожеланный выход.

    <select ng-model="item.foodItem" ng-options="food.name as food.name for food in foods">
    

    результаты в выходе:

    <option label="Cabbage" value="string:Cabbage" selected="selected">Cabbage</option>
    

    Этого небольшого изменения в выходных данных достаточно для angular, чтобы найти соответствие строкового значения $scope.recipe.ingredientsи установить значение по умолчанию.

    http://plnkr.co/edit/3l1afYx4n4xRAlPuzWkZ?p=preview