Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ng-options not binding when it has preselected values

I am using select2 to create a div with tags like functionality when creating a new post.

Stack is Angular 1.6.x

It works well when I am creating a new post BUT when I add pre-selected values when editing the said post, the preselected values never change from the default.

In a nutshell, the values are not binding.

See below:

HTML snippet:

<div class="form-group">
  <label for="tags" class="control-label">Tags</label>
    <select name="tags" class="tagsSearch" class="form-control" id="tags"
            ng-options="tag as tag for tag in post.tags track by tag"
            ng-model="post.tags" style="width: 100%" multiple>
    </select>
</div>

Note: it looks messy but I got this to work to show my original tags

Controller snippet:

$http.get('/api/post', {params: { title: $scope.title }})
.then(function(res){
   $scope.post = res.data.post;
});

$scope.updatePost = function() {
  console.log($scope.post.tags);
};

The problem is that the tags do not bind, so if the values are: tag1, tag2, tag3 at rendering and I add: tag4 - updatePost consoles tag1, tag2 and tag3

PS: My tags are an array of strings and have no keys to it like an ID (saw some other post which was referencing to them).

Very lost. Any input would be highly appreciated.

Thanks

EDIT - 28th April 2018:

I have updated my tags to be objects of an array like this:

[
  {tag: "tag1", _id: "5ae410756b7a61080cd17c81"},
  {tag: "tag2", _id: "5ae410756b7a61080cd17c80"},
  {tag: "tag3", _id: "5ae410756b7a61080cd17c7f"}
]

It still doesn't work when I do it like this:

<select name="tags" class="tagsSearch" class="form-control" id="tags"
        ng-options="tag as tag.tag for tag in post.tags track by tag._id" 
        ng-model="post.tags" style="width: 100%" multiple>
</select>

The console.log still only captures the pre-existing tags. New ones are ignored.

like image 982
Shayan Khan Avatar asked Apr 02 '18 04:04

Shayan Khan


People also ask

What is the difference between Ng-options and Ng-repeat?

ng-repeat creates a new scope for each iteration so will not perform as well as ng-options. For small lists, it will not matter, but larger lists should use ng-options. Apart from that, It provides lot of flexibility in specifying iterator and offers performance benefits over ng-repeat.

What is the difference between Ngmodel and Ng-bind?

ng-bind is also used for data binding but unlike ng-bind it supports only one way data binding.It is used for displaying model properties as innerHTML of html elements such as div and span. This is unlike ng-model which is used for binding input fields and supports two way data binding.

Why do we use NG-repeat?

Definition and Usage The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

Does ng If create a new scope?

Note that when an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored. The scope created within ngIf inherits from its parent scope using prototypal inheritance.


2 Answers

Below implementation might be what you asked for:

HTML:

 <form name="myForm">
    <label for="mySelect">Make a choice:</label>
    <select name="mySelect" id="mySelect"
      ng-options="option.tag for option in post.tag track by option._id"
      ng-model="post.selected" multiple></select>
      <br>
      <button ng-click="updatePost()"> Add Tag</button>
 </form>

JS:

(function(angular) {
  'use strict';
  angular.module('defaultValueSelect', [])
    .controller('ExampleController', ['$scope', '$http', function($scope, $http) {
      var url = "https://jsonblob.com/api/jsonBlob/aa6b4eb4-5284-11e8-a5ee-fd00735e3b38";
      var index = 4;
      var extraObj = {
        tag: "tag",
        _id: "5ae410756b7a61080cd17c7"
      };
      $http
        .get(url)
        .then(function(response) {
          $scope.post = {
            tag: response.data,
            selected: response.data[0]
          };
        });
      $scope.updatePost = function() {
        var tmp = {};
        tmp = angular.copy(extraObj);
        console.log(angular.copy($scope.post));
        tmp.tag += index;
        tmp._id += index;
        $scope.post.tag.push(tmp);
        console.log($scope.post);
        index++;
      }
    }]);
})(window.angular);

For working code refer to this plunkr: plnkr.co/edit/cwDRa2Qjg2IlUi5JOAPj

like image 147
Abhishek Singh Avatar answered Oct 19 '22 01:10

Abhishek Singh


I used angular select documentation as a reference and created a plunker from their example found here.

I used this blob to simulate your data set.

This is what my select directive looks like. I would suggest that you not overwrite the binding for the array with the bind for the selected item, that is what is causing you problems.

(function(angular) {
  'use strict';
angular.module('defaultValueSelect', [])
  .controller('ExampleController', ['$scope','$http', function($scope,$http) {
    var url = "https://jsonblob.com/api/jsonBlob/aa6b4eb4-5284-11e8-a5ee-fd00735e3b38";
    $http
        .get(url)
        .then(function(response){
            $scope.post = {
                tag: response.data,
                selected: response.data[0]
            };
        })
 }]);
})(window.angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="defaultValueSelect">
  <div ng-controller="ExampleController">
  <form name="myForm">
    <label for="mySelect">Make a choice:</label>
    <select name="mySelect" id="mySelect"
      ng-options="option.tag for option in post.tag track by option._id"
      ng-model="post.selected" multiple></select>
  </form>
  <hr>
  <tt>option = {{post.selected}}</tt><br/>
</div>
</body>

Happy Coding

like image 28
EmptyCup Avatar answered Oct 19 '22 01:10

EmptyCup