简体   繁体   中英

Angular JS Push Empty Object To Array

I've been working a project that allows a user to manage Option Types and Options. Basically user can add a new Option Type, let's say they name it Color and then they add the options - Black, Red, Purple, etc. When the collection first loads up the existing records, an empty option should be added at the end

When a user starts typing in the text field, I want to add a new empty option , thereby always giving the user a new field to work with.

I have this almost working, but can't figure how to properly add new empty option to a new Option Type or to existing option types. The push method keeps crashing Plunkr. Any input is appreciated, short sample review of the plunkr is below

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

app.controller('MainCtrl', function($scope) {

$scope.optionTypeId = 0;
$scope.productOptionId = 0;

$scope.productEditorModel = {
  "ProductOptions": [0],
  "OptionTypes": [0]
};

$scope.productEditorModel.optionTypeName = '';

$scope.addEmptyOption = function (optionTypeId) {

var emptyOption = { ProductOptionId: 3, ProductId: '1066', OptionTypeId: 1, OptionValue: '', Price: '', IsStocked: true };
console.log(emptyOption);
//$scope.productEditorModel.ProductOptions.push(emptyOption);
};

$scope.loadData = function () {

$scope.productEditorModel.OptionTypes = [{ OptionTypeId: 1, OptionName: 'Color' },{ OptionTypeId: 2, OptionName: 'Size' },];
  $scope.productEditorModel.ProductOptions = [{ ProductOptionId: 1, ProductId: '1066', OptionTypeId: 2, OptionValue: 'Medium', Price: '', IsStocked: true, },{ ProductOptionId: 2, ProductId: '1066', OptionTypeId: 1, OptionValue: 'Black', Price: '', IsStocked: true }];

angular.forEach($scope.productEditorModel.ProductOptions, function (item) {
      //console.log(item.OptionTypeId);
      $scope.addEmptyOption(item.OptionTypeId);
});
};

$scope.loadData();

$scope.removeOption = function (option) {
        var index =   $scope.productEditorModel.ProductOptions.indexOf(option);
        $scope.productEditorModel.ProductOptions.splice(index, 1);
};

$scope.filterEmptyElements = function (optionTypeId) {
$scope.emptyElements = $.grep($scope.productEditorModel.ProductOptions, function (k) { return k.OptionValue === "" || angular.isUndefined(k.OptionValue) && k.OptionTypeId == optionTypeId });
};

$scope.update = function (option, index) {
  var optionTypeId = option.OptionTypeId;
  $scope.filterEmptyElements(optionTypeId);

  if (!angular.isUndefined(option.OptionValue) && $scope.emptyElements.length == 1 && option.OptionValue.length > 0) {
      $scope.addOption(optionTypeId);
  } else if (angular.isUndefined(option.OptionValue)) {
      $scope.removeOption(option);
  }
}; 

$scope.addOptionType = function () {
  var optionTypeId = --$scope.optionTypeId;
  var optionName = $scope.productEditorModel.optionTypeName;
  var newOptionType = { OptionTypeId: optionTypeId, OptionName: optionName    };

  $scope.productEditorModel.OptionTypes.push(newOptionType);
  $scope.addEmptyOption(optionTypeId);
};

$scope.editOptionType = function (optionType) {
  $scope.editing = true;
};

$scope.saveOptionType = function (optionType) {
  $scope.editing = false;
};

$scope.trackOptionTypesCount = function () {
if ($scope.productEditorModel.OptionTypes.length == 3) {
    $scope.isMaxOptionTypes = true;
} else {
    $scope.isMaxOptionTypes = false;
}
};

$scope.removeOptionType = function (optionType) {
  var index = $scope.productEditorModel.OptionTypes.indexOf(optionType);
  $scope.productEditorModel.OptionTypes.splice(index, 1);
  $scope.trackOptionTypesCount();
};
});

See the plunker below: http://plnkr.co/edit/YHLtSwQWVb2swhNVTQzU?p=info

The error you get that $ is not defined is because you haven't included jQuery. You don't need jQuery for this though, array.map should be able to perform the same functionality.

$scope.emptyElements = $scope.productEditorModel.ProductOptions.map(function (k) { 
   return k.OptionValue === "" || angular.isUndefined(k.OptionValue) && k.OptionTypeId == optionTypeId 
});

And it crashes because inside $scope.loadData you have

angular.forEach($scope.productEditorModel.ProductOptions, function (item) {
    $scope.addEmptyOption(item.OptionTypeId);
});

and then inside $scope.addEmptyOption you try to

$scope.productEditorModel.ProductOptions.push(emptyOption);

So the foreach will loop for each item in $scope.productEditorModel.ProductOptions , which you keep adding options to so....? Infinite loop.

Non-crashing version: http://plnkr.co/edit/5Sc2sWfhKBs9kLCk83f1?p=preview

What you really should do though is look over your data structure. Make the ProductOptions a sub-object of OptionTypes and just rename it Options. Remove ALL code about creating id's here in your GUI, that should be handled by the backend. Instead in the GUI there should be a Sortorder property on the Options (which also of course gets stored by the backend). Then when you store, the ones without an id get inserted, the ones with an id get updated. Much easier to handle everything that way.

I'd also break out optionTypes and options to their own services/providers. Much easier to keep track of what needs to be done. And each just basically contains add, remove and maybe a find/getJSON or something.

Here's a restructured version. Much easier to keep track of what belongs where. And it has more features than the original with less code. http://plnkr.co/edit/BHcu6vAfcpEYQpZKHc5G?p=preview

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM