3

I'm trying to join/combine two arrays in angular ng-repeat.

Simple example book/author where I want to print book titles with coresponding author name.

Books are in one array, authors in another.

How to join data in this example?

JSFiddle: http://jsfiddle.net/1jxsh0x3/

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

function MyCtrl($scope) {

  $scope.authors = [{
    id: "1",
    name: "John"
  }, {
    id: "2",
    name: "Peter"
  }, {
    id: "3",
    name: "Mark"
  }];
  
  $scope.books = [{
    id: "1",
    id_author: "3",
    name: "Book Lorem"
  }, {
    id: "2",
    id_author: "1",
    name: "Book Ipsum"
  }, {
    id: "3",
    id_author: "1",
    name: "Book Dark"
  }];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-controller="MyCtrl">
  <div ng-repeat="book in books">
    <div>Book title: {{book.name}}</div>
    <div>Authors name: {{authors[$index].name}}</div>
    <hr>
  </div>
</div>

2
  • You want to show the data based on the id which is unique. Not index? Commented Jul 19, 2017 at 7:02
  • @SaiUnique, yes Commented Jul 19, 2017 at 7:03

8 Answers 8

3

EDIT: At least AngularJS 1.2 is required

I would use angulars filter:

<div>
    Authors name: {{authors[$index].name}}
</div>

to:

<div>
    Authors name: {{(authors | filter:{'id': book.id_author}:true)[0].name}}
</div>

What we are doing here is taking the array authors and filter it by the expression 'id': book.id_author and we take the .name of the first element of this filtering ([0]).

Just in case you could check if you actually have the author in your array:

<div>
    Authors name: {{(authors | filter:{'id': book.id_author}:true) 
                     ? (authors | filter:{'id': book.id_author}:true)[0].name
                     : 'Unknown'}}
</div>

Best regards

PS (EDIT): fiddle with angular 1.2.6 -> http://jsfiddle.net/gqqv9k38/1/

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

3 Comments

There is a problem if there is for example author with id:11, it shows that author, not author with id:1
Hi, it is not strict but true what should be on the code, I already edited it. The reason it does not work on the fiffle is because the fiddle is using angular 1.0.1, is this the angular version you are using?
The fiddle with angular 1.2.6 for example jsfiddle.net/gqqv9k38/1
2

This is the most optimized solution for your problem.

Put the below code in your controller file -

$scope.entries = [];
angular.forEach($scope.books,function(entry) {
    var author_name;
    var searchField = "id";
    var searchVal = entry.id_author;
    author_name = getAuthorName(searchField,searchVal,$scope.authors)
    $scope.SubInformation['author_name'] = author_name;
    $scope.entries.push(angular.extend(entry,$scope.SubInformation);   
});

function getAuthorName(searchField,searchVal,authors){
    for (var i=0 ; i < authors.length ; i++)
    {
        if (authors[i][searchField] == searchVal) {
            return authors[i]['name'];
        }
    }
}

And update your view file with below code :

<div ng-controller="MyCtrl">
  <div ng-repeat="book in entries">
    <div>Book title: {{book.name}}</div>
    <div>Authors name: {{book.author_name}}</div>
    <hr>
  </div>
</div>    

Comments

2
  1. You can create custom findAuthor method
  2. Use common filter with strict to select exactly needed author id instead of similar

angular.module('app',[])
.controller('ctrl', function($scope){

  $scope.authors = [{
    id: "1",
    name: "John"
  }, {
    id: "11",
    name: "Peter"
  }, {
    id: "3",
    name: "Mark"
  }];
  
  $scope.books = [{
    id: "1",
    id_author: "3",
    name: "Book Lorem"
  }, {
    id: "2",
    id_author: "1",
    name: "Book Ipsum"
  }, {
    id: "3",
    id_author: "1",
    name: "Book Dark"
  }];
  
    
  $scope.findAuthor = function(id){
    return $scope.authors.find(function(x){
	    return x.id == id
   })};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<h4>1. findAuthor metod</h4>
<div ng-app='app', ng-controller='ctrl'>  
  <div ng-repeat="book in books">
      <div>Book title: {{book.name}}</div>
      <div>Authors name: {{findAuthor(book.id_author).name}}</div>
      <hr>
  </div>
  
<h4>2. With help of filter</h4>    
  <div ng-repeat="book in books">
    <div>Book title: {{book.name}}</div>
    <div>Authors name: {{(authors | filter: {'id': book.id_author}: strict)[0].name}}</div>
    <hr>
  </div>

</div>

Comments

0

You can do like this:

<div ng-repeat="book in books">
    <div>Book title: {{book.name}}</div>
    <div>Authors name: {{getAuthorName(book.id_author)}}</div>
</div>

in js:

$scope.getAuthorName(id) {
    var name;
    name = $scope.authors.find(function(author) {
        if(author.id_author === id) {
            return author.name;
        }
    }) 
    return name;
}

Hope this helps :)

Comments

0

create the function and filter the name according to id

$scope.getName = function(obj){

    return $scope.authors.find(o=>{
      if(o.id == obj.id_author){return o }
    })
  }

call it like this

<div ng-controller="MyCtrl">
  <div ng-repeat="book in books">
    <div>Book title: {{book.name}}</div>
    <div>Authors name: {{getName(book).name}}</div>
    <hr>
  </div>
</div>

Demo

Comments

0

You can simply compare the values and add it to the books model. It can be done as shown below:

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

    function MyCtrl($scope) {

      $scope.authors = [{
        id: "1",
        name: "John"
      }, {
        id: "2",
        name: "Peter"
      }, {
        id: "3",
        name: "Mark"
      }];
      
      $scope.books = [{
        id: "1",
        id_author: "3",
        name: "Book Lorem"
      }, {
        id: "2",
        id_author: "1",
        name: "Book Ipsum"
      }, {
        id: "3",
        id_author: "1",
        name: "Book Dark"
      }];
      
      
      for(var i = 0; i < $scope.books.length; i++){
          var id = $scope.books[i].id_author;
          for(var j = 0; j < $scope.authors.length; j++){
              if($scope.authors[j].id ==  $scope.books[i].id_author ){
               $scope.books[i].authorName =  $scope.authors[j].name;
              }
          }
      }
      
   }




   
    
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app = "myApp">
    <div ng-controller="MyCtrl">
        <div ng-repeat="book in books">
            <div>Book title: {{book.name}}</div>
            <div>Authors name: {{book.authorName}}</div>
            <hr>
        </div>
    </div>
</html>

Comments

0

You can merge both JSON data into new array

 var  newArray= authors.map(x => Object.assign(x, books.find(y => y.id == x.id)));

Comments

0

Here is your answer, with demo :) ..your author array must be sorted in my case ;)

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

function MyCtrl($scope) {

  $scope.authors = [{
    id: "1",
    name: "John"
  }, {
    id: "2",
    name: "Peter"
  }, {
    id: "3",
    name: "Mark"
  }];

  $scope.books = [{
    id: "1",
    id_author: "3",
    name: "Book Lorem"
  }, {
    id: "2",
    id_author: "1",
    name: "Book Ipsum"
  }, {
    id: "3",
    id_author: "1",
    name: "Book Dark"
  }];



}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="myApp">
<div ng-controller="MyCtrl">
  <div ng-repeat="book in books">
    <div>Book title: {{book.name}}</div>
    <div>Authors name: {{authors[book.id_author -1].name}}</div>
    <hr>
  </div>
</div>

</html>

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.