Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I am developing an online course application and I am trying to display the course details of a course along with video lectures which are on youtube. My angular controller is fetching the course details from the node.js controller and displaying it on the html view, however it doesn't show get the youtube video link. Its because I changed the mongoose schema for storing course video from a String to String Array. If I keep the mongoose schema for course video as String, then I can view the video.

Here is the mongoose schema, file name is course.server.model.js

'use strict';

/**
* Module dependencies
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;

/**
* Course Schema
*/
var CourseSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
content: {
type: String,
default: '',
trim: true
},
courseLecture: [{
week_number: { type: Number },
lecture_video: [String]
}],
user: {
type: Schema.ObjectId,
ref: 'User'
}
});

mongoose.model('Course', CourseSchema);

In the schema, I have kept lecture_video as String array within courseLecture.

Here is my angular controller. controller name is courses.client.controller.js

(function () {
'use strict';

angular
.module('courses')
.config(function($sceDelegateProvider) {
  $sceDelegateProvider.resourceUrlWhitelist([
    'self',
    'https://www.youtube.com/**'
  ]);
})
.controller('CoursesController', CoursesController);

CoursesController.$inject = ['$scope', 'courseResolve', 'Authentication'];

function CoursesController($scope, course, Authentication) {
var vm = this;

vm.course = course;
vm.authentication = Authentication;

$scope.product = {
  name: 'some name',
  description: 'some description',
  media: [{
    src: vm.course.courseLecture.lecture_video
  }]
};

console.log('value of courseLecture: ' + vm.course);

console.log('value of youtube embed lecture is: ' + vm.course.courseLecture.lecture_video);

$scope.getIframeSrc = function(src) {
  return 'https://www.youtube.com/embed/' + src;
};
}
}());

If I do console.log for vm.course.courseLecture.lecture_video then I get undefined. However, I do get undefined for it, even from node.js controller as well.

Here is my html view. file name :- view-course.client.view.html

<style>
.video-container {
height: 400px;
width: 200px;
}
.thumbnail1 {
height: 450px;
width: 220px;
}
</style>
<section>
<div class="page-header">
<h1 ng-bind="vm.course.title"></h1>
</div>
<small>
<em class="text-muted">
  Posted on
  <span ng-bind="vm.course.created | date:'mediumDate'"></span>
  by
  <span ng-if="vm.course.user" ng-bind="vm.course.user.displayName"></span>
  <span ng-if="!vm.course.user">Deleted User</span>
</em>
</small>
<p class="lead" ng-bind="vm.course.content"></p>
<div ng-repeat="media in product.media">
<div class="thumbnail1" class="col-xs-12 col-sm-9">
  <div class="video-container">
    <iframe ng-src="{{getIframeSrc(media.src)}}" frameborder="5" allowfullscreen></iframe>
  </div>
</div>
</div>
</section>

Right now with this, I can see the course details using REST calls, only the video link doesn't work, which starts working if in the course schema, in the courseLecture property, if I change the lecture_video from lecture_video: [String] to lecture_video: {type:String}. I can view the video. I want to store all the video links for a week in an array so the all the videos can be displayed. Please help me with what I am doing wrong here.

share|improve this question
up vote 1 down vote accepted

If you got data according to your schema then your angular controller can be like bellow to add each video url in media. because your courseLecture is an array and in courseLecture the lecture_video also an array so need to iterate as media array so need two forEach or for loop.

$scope.product = {
    name: 'some name',
    description: 'some description',
    media: []
  };

  (vm.course.courseLecture).forEach(function(lecture) {
    (lecture.lecture_video).forEach(function(videoUrl) {
      $scope.product.media.push({src: videoUrl});
    });
  });

and Html

<div ng-repeat="media in product.media">
    <div class="thumbnail1 col-xs-12 col-sm-9" >
      <div class="video-container">
        <iframe ng-src="{{getIframeSrc(media.src)}}" frameborder="5" allowfullscreen></iframe>
      </div>
    </div>
  </div>
share|improve this answer
    
With this, I'm not getting the other details as well on the page now, like course title, course content. I'm getting a blank page now. – Vikas Pandey 20 hours ago
    
but why I did not change your other code without media. others code should be working if previous was working well. I have shown only what should for media @VikasPandey – Shaishab Roy 20 hours ago
    
I think you got me wrong. I'm not talking about product.name or product.description values. They are just dummy's. I'm talking about the course content I am getting from mongodb. That content is not getting displayed now. I think in this line, $scope.product.push({src: videoUrl}); , it should be modified to $scope.product.push({src: videoUrl}, media); then it should work . I didn't tested though. @shaishab-roy – Vikas Pandey 20 hours ago
    
can you show me your actual data that come from mongodb? @VikasPandey – Shaishab Roy 20 hours ago
    
right now i'm getting, TypeError: $scope.product.push is not a function. At both the forEach loop. at localhost:3000/modules/courses/client/controllers/… at Array.forEach (native) at localhost:3000/modules/courses/client/controllers/… @shaishab-roy – Vikas Pandey 19 hours ago

Since the type has changed, there will be inconsistency in the data that is coming from rest. Hence, You have to provide backward compatibility for the string url as well as the array of string urls.

For string urls :

<div ng-if="isString(product.media)">
<div class="thumbnail1" class="col-xs-12 col-sm-9">
  <div class="video-container">
    <iframe ng-src="getIframeSrc(product.media.src)" frameborder="5" allowfullscreen></iframe>
  </div>
</div>
</div>

For Array of string url :

<div ng-if="!isString(product.media)">
    <div ng-repeat="media in product.media">
    <div class="thumbnail1" class="col-xs-12 col-sm-9">
      <div class="video-container">
        <iframe ng-src="{{getIframeSrc(media.src)}}" frameborder="5" allowfullscreen></iframe>
      </div>
    </div>
</div>
</div>

In controller :

$scope.isString = function(media){
    if(Array.isArray(media)){
        return false;//returns if it is an string
    }
    else{
        return true; // return if it is an array
    }
}
share|improve this answer
    
This doesn't play video. There is no difference in the result. I think, I need one more loop for media, since video_lecture is also an array. @bala-abhinav – Vikas Pandey 19 hours ago
    
Sure, This was just to give an example of what i said. I would suggest you to change it accordingly to your data model.. – Bala Abhinav 19 hours ago

vm.course.courseLecture[0].lecture_video is an array which has an array of videos in the schema. In client you create $scope.product with media key which has an array value, inside is a object again with key src which should have the value vm.course.courseLecture[0].lecture_video. product.media.src[0] is the key you want to iterate.

<div ng-repeat="media in product.media.src[0]">
<div class="thumbnail1" class="col-xs-12 col-sm-9">
  <div class="video-container">
    <iframe ng-src="{{getIframeSrc(media)}}" frameborder="5" allowfullscreen></iframe>
  </div>
</div>
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.