Question

I am trying to do the following quite unsuccessfully so far.

I have an string that is semicolon separated. Say a list of emails, so

'email1@example.com;email2@example.com;email3@example.com'

What I am trying to accomplish is split this string (using split(';')) into an array of strings or array of objects (to aid binding). Each of the items I would like to bind to different input elements. After editing I want to read the concatenated value again to send to my backend.

Problem is that when editing one of the split inputs, the original item value is not update (which makes sense as I am guessing the individual items are copies of parts of the original), but I am wondering if there is a way to do something like that. Note that I want this to go both ways, so watching the individual inputs and updating the original one manually, would just fire an infinite loop of updates.

I have tried a few different ways, including creating an items property get/set using Object.defineProperty to read and right to the string (set was never fired).

take a look at this plnker

Was it helpful?

Solution

You can construct a temporary array on each field update in order to do the string replacement of the old segment with the new value. In order to tackle the lost focus problem you will have to use the ngReapeat's track by $index. The internal array will not be recreated unless you add the separator to your original string.

Here is the complete solution on Plunker

OTHER TIPS

Your main issue is your ng-model attribute on your repeated input element. I would start with making use of ng-repeat's $index variable to properly bind in ng-model. In your original Plunker 'name' is NOT a scope property you can bind to, so this should be changed to ng-model="names[$index]"

Here is a Plunker to reflect this. I made quite a few changes for clarity and to have a working example.

NOTE: You will find that when editing fields directly bound to a repeater, every change will fire a $digest and your repeated <input> elements will refresh. So the next issue to solve is regaining focus to the element you are editing after this happens. There are many solutions to this, however, this should be answered in a different question.

Although binding to a string primitive is discouraged, you could try ng-list.

<form name="graddiv" ng-controller="Ctrl">
  List: <input name="namesInput" ng-list ng-model="vm.names"/>
  <ul>
    <input ng-repeat="name in vm.names track by $index" ng-model="name" ng-change="updateMe($index, name)"/>
  </ul>

You'll need both track by $index and an ng-change handler because of the primitive string binding.

function Ctrl($scope) {
  $scope.vm = {}; // objref so we can retain names ref binding
  $scope.vm.names = ['Christian', 'Jason Miller', 'Judy Dobry', 'Bijal Shah', 'Duyun Chen', 'Marvin Plettner', 'Sio Cheang', 'Patrick McMahon', 'Chuen Wing Chan'];
  $scope.updateMe = function($index, value){
    // ng quirk - unfortunately we need to create a new array instance to get the formatters to run
    // see http://stackoverflow.com/questions/15590140/ng-list-input-not-updating-when-adding-items-to-array
    $scope.vm.names[$index] = value; // unfortunately, this will regenerate the input
    $scope.vm.names = angular.copy($scope.vm.names); // create a new array instance to run the ng-list formatters
  };
}

Here's your updated plunkr

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top