Paul Radich Paul Radich - 4 months ago 38
JSON Question

Multiple feeds in one template - Angularjs and Ionic

I am using ionic to create a news app of sorts. The main news stream is a JSON feed from a wordpress site. There is a second JSON feed from my server that fetches tweets.

The goal is to mix the tweets into the news feed. So the output might look like.

news article

news article

news article

tweet

tweet

news article

news article

tweet

news article

news article

I have it working but there has to be a better more flexible way. I have two current problems.

1.) the two feeds are nothing alike so combining them in the controller does not seem like an option.

2.) I need it to be flexible so the number of tweets and the number of twitter feeds can be changed.

Currently I am splitting the news feed and using the view to put it all together. Here is what I have so far

<ion-list>

<!--3 items from news feed-->
<ion-item ng-repeat="post in postSet1">
<a nav-transition="ios" ui-sref="post({post:post})">
<img src="" ng-src="{{post.thumbnail_images.full.url}}" alt="" class="post_thumb" ng-if="post.thumbnail_images.full.url">
</a>
<br>
<div class="post-meta">
<div class="post-time">
Posted 6 hours ago <i class = "icon icon ion-android-share-alt"></i>
<br class="clear">
</div>
</div>
<a nav-transition="ios" ui-sref="post({post:post})">
<div class="post-text" ng-bind-html="post.title"></div>
</a>
</ion-item>

<!--3 tweets-->
<ion-item ng-repeat="tweet in tweets | limitTo:3" class="tweet">
<a nav-transition="ios" ui-sref="post({post:post})">
<div class="left">
<img src="" ng-src="{{tweet.user.profile_image_url}}" alt="">
</div>

<div class="right">
<b>{{tweet.user.name}}</b> @{{tweet.user.screen_name}}
<br>
{{tweet.text}}
</div>
<br class="clear">
</a>
</ion-item>

<!--All the rest of the news feed-->
<ion-item ng-repeat="post in postSet2 ">
<a nav-transition="ios" ui-sref="post({post:post})">
<img src="" ng-src="{{post.thumbnail_images.full.url}}" alt="" class="post_thumb" ng-if="post.thumbnail_images.full.url" >
<br>
<div class="post-meta">
<div class="post-time">
Posted 6 hours ago <i class = "icon icon ion-android-share-alt"></i>
<br class="clear">
</div>
</div>
<div class="post-text" ng-bind-html="post.title"></div>
</a>
</ion-item>

</ion-list>


I hope I explained this well enough and you can lend some help.

Answer

It does make sense to mix the two different feeds in your controller into the same array. You just need to label them with a property in the controller so the view knows what to render via ng-if. In this example using a filter to generate a random order with numbers.

If you want a specific order ie [3, 3, rest of newsfeed] like your above example you can manipulate the controller a little and remove the random orderBy filter. Let me know if you prefer this and I can write it up.

EDIT - moved the entire newsfeed or tweet block inside a div where the ng-if occurs

html

<ion-list>
  <ion-item ng-repeat="post in data | orderBy:random">

    <!-- ng-if to render newsfeed template block-->
    <div ng-if="post.isNewsfeed">
      <a nav-transition="ios" ui-sref="post({post:post})">
        <img src="" ng-src="{{post.thumbnail_images.full.url}}" alt="" class="post_thumb" ng-if="post.thumbnail_images.full.url">
      </a>
      <br>
      <div class="post-meta">
         <div class="post-time">
           Posted 6 hours ago <i class = "icon icon ion-android-share-alt"></i>
          <br class="clear">
         </div>
      </div>
      <a nav-transition="ios" ui-sref="post({post:post})">
        <div class="post-text" ng-bind-html="post.title"></div>
      </a>
    </div>

    <!-- ng-if to render tweet template block -->
    <div ng-if="post.isTweet">
      <a nav-transition="ios" ui-sref="post({post:post})">
        <div class="left">
          <img src="" ng-src="{{post.user.profile_image_url}}" alt="">
        </div>

        <div class="right">
          <b>{{post.user.name}}</b>   @{{post.user.screen_name}}
          <br>
          {{post.text}}
        </div>
        <br class="clear">
      </a>
    </div>

  </ion-item>
</ion-list>

controller

.controller('NewsfeedCtrl', function($scope, $http, $q, $timeout) {
  // this is where you control the number of max tweets and max newsfeed items to display
  angular.extend($scope, {
    maxTweets: 3,
    maxNewsfeed: 6,
    data: []
  });

  // filter to generate random order in ng-repeat
  $scope.random = function() {
    return 0.5 - Math.random();
  };

  var getTweets = $http.get('http://gettweets.com/api/');
  var getNewsfeed = $http.get('http://getnewsfeed.com/api/');

  $q.all([getTweets, getNewsfeed]).then(function(res) {
    var tweets = res[0];
    var newsfeed = res[1];

    // use max tweets and max newsfeed to cut array
    tweets = tweets.splice(0, $scope.maxTweets);
    newsfeed = newsfeed.splice(0, $scope.maxNewsfeed);

    // mark each tweet or newsfeed as such for ng-if in template
    tweets.forEach(function(tweet) { tweet.isTweet = true });
    newsfeed.forEach(function(item) { item.isNewsfeed = true });

    // combine both into a scope variable to be used in an ng-repeat
    $scope.data = tweets.concat(newsfeed); 
    $timeout();
  }, function(err) {
    console.error(JSON.stringify(err));
  });

})