2

How can I convert between a delimited string and an array of objects with data binding?

ng-list will work with an array of strings. But I have an array of objects, in which I would like to delimit the text property so the text in the array can be editable.

Works with Array of Strings:

$scope.arrayStrings = ["one", "two", "three"];
<textarea ng-model="arrayStrings" ng-list="&#10;" ></textarea>

How can I get this to work with objects:

$scope.arrayObjects = [{
  text: "one",
  selected: true
}, {
  text: "two",
  selected: true
}, {
  text: "three",
  selected: true
}];
<textarea ng-model="arrayObjects" ng-list="&#10; | text" ></textarea>

Here's a demo in plunker


One possible idea I had was to use ng-list on the array of strings and then map that to the array of objects. The use a $watch to update the object array anytime the string array changed. However, this still falls short because it will overwrite any other properties on the object every time the array updates. (Demo in previous plunker revision)

$scope.$watch('arrayStrings', function() {
  $scope.arrayObjects = $scope.arrayStrings.map(function(s){
    return {
      text: s,
      selected: true
    }
  });
})

Update:

There still seem to be issues when using ng-list even when using Krzysztof's suggestion:

toString: function() { return s }

Overriding the toString method helps the set of objects when initially displayed, but as soon as you type anything, ng-list converts the set of objects back into an array of strings because at that point toString has not come into play.

To clarify what I'm trying to do. I really want a list of objects, with editable titles, that can also be selected. I'd like to preserve selections even when the title has changed or items have been added.

Here's another plunker to demonstrate

screenshot

3
  • 1
    method toString() should be help for you – plnkr.co/edit/3CEQDkkGGv52L0jpRaRq?p=preview Commented Jul 26, 2014 at 0:04
  • @Krzysztof Safjanowski, post that as an answer, it sure is educational! Commented Jul 26, 2014 at 1:44
  • Thanks @ryeballar for inspiration Commented Jul 26, 2014 at 1:57

2 Answers 2

2

toSting()

JavaScript uses method toString() to represent text value. By default, the toString() method is inherited by every object descended from Object. If this method is not overridden in a custom object, toString() returns "[object type]", where type is the object type.

Overwriting toSting()

Method `toSting() can be overwritten as almost everything in JavaSctript

$scope.arrayObjects = $scope.arrayStrings.map(function(s){
    return {
        text: s,
        selected: true,
        toString: function() {
            return '{text: "' + s + '"}' // this will be returned instead of [object Object]
        }
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the advice. Although, it's still override the list whenever I type anything. I updated my question with a clarification. I think ng-list is converting each comma separated entry, regardless of what the toString method is.
1

While Krzysztof's suggestion was helpful, I couldn't quite get the binding to work with ng-list because the ng-list will always convert the array of objects into an array of strings, thus overriding any objects I had on scope.

In this case, the simplest thing to do was to upgrade from ng-list to something with full object support like most tagging libraries:

I Implemented ngTagsInput like this:

HTML:

<tags-input ng-model="arrayObjects" display-property="text"></tags-input>

JavaScript:

$scope.arrayObjects = [
  { "text": "one"   , "selected": false },
  { "text": "two"   , "selected": false },
  { "text": "three" , "selected": false }
];

This way each object is given it's own element where the text property is displayed and they are all formatted together to live inside of an input. Changing one object just updates that single element

Demo in Pluner

Comments

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.