3

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

4
  • so whats your issue? Commented Jul 2, 2015 at 17:58
  • Issue is that I am unable to figure out how to add a new option to each option type when user types into the field. Then another issue occurs with the indexes when a user adds a new Option Type. Commented Jul 2, 2015 at 18:03
  • Still unclear but I think you want to use an ng-repeat bound to a list of options and another for each option's list of optionTypes Commented Jul 2, 2015 at 18:34
  • I updated the Plunkr, everythign is working but the add empty option. can't figure it out, sorry for the lack of clarity, its rough trying to write code and babysit two kids lol Commented Jul 2, 2015 at 21:35

1 Answer 1

0

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

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks for that, I'm kinda new to angular so I totally forgot that the loop would be infinite. What do you think about using ng-init to call loadData, I believe ng-init is only executed once.
The problem isn't with executing once, the problem is that you're adding items to the array you're iterating over for each iteration over the array. Kinda like if you were doing this. while (i < j) { i++; j++; }. if i is smaller than j to begin with, i will always be smaller than j since you're increasing both so you will never exit the loop. But why do you need to add items to ProductOptions if the items are there to begin with? You probably want to load them from a setting file/json/sql call, and then you could just bind the loaded array to ProductOptions, no need to iterate.
Here's a mock of what you'd actually want to be doing. Suggestions for fixing a few other bugs too. plnkr.co/edit/t0hUTt6u1UcTxYyKRGEd?p=preview
Thanks for the knowledge...the reason why I want to add items to existing ProductOptions is because I always want a new empty option there for the user to work with.
Lol, after my 2nd cup of coffee I realized I should set it local to the object, not to the global scope like you mentioned :) I need to treat angular just like regular OOP code, b/c it's pretty much the same in regards to objects, scope and other factors.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.