Angular duplicate items - javascript

I've got a problem.
I have a JSON comming from backend to my frontend. It looks like:
{
"title": "Interrupted",
"image": "1",
"timestamp": "1403617939848",
"image" : "1",
"categories": ["News","News","Handball","Handball"]
},
My view looks like:
<!doctype html>
<html class="no-js" lang="" ng-app="videoApp">
<head>
<meta charset="utf-8">
<title>Latest videos</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Cache-Control" content="public">
<link rel="stylesheet" href="css/normalize.css">
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/libraries/bootstrap.min.css">
</head>
<body ng-controller="VideoListCtrl">
<header class="col-lg-12 col-md-12 col-sm-12 text-white">
LATEST VIDEOS
<span><select class="favorite-selector">
<option value="{{category}}" ng-repeat="category in categories">{{category}}</option>
</select> <button class="btn-danger">Add to favorite</button></span>
<span class="results"></span>
</header>
<main>
<div class="category-list">
<li>All videos</li>
<li ng-repeat="category in categories"> {{category}}</li>
</div>
<div class="video-container" id="video-container">
<article class='col-lg-3 col-md-4 col-sm-12 col-xs-12 video' dir-paginate="video in videos | itemsPerPage: 12">
<div class='video-image'><img class='img-responsive img' src='img/{{video.image ? video.image : "1" }}.jpeg'>
<img class='player img-responsive' src='img/icon.png' width='75px' height='75px'>
</div>
<p class='video-title'><strong>{{video.title}}</strong></p>
<p class='video-timestamp'>{{video.timestamp}}</p>
<span class='categories'>
<li ng-repeat="categ in video.categories | unique">{{categ}} </li>
</span>
</article>
</div>
<div class="col-lg-offset-2 col-lg-8">
<dir-pagination-controls></dir-pagination-controls>
</div>
</main>
<script src="js/angular/angular.js"></script>
<script src="js/angular/ui-utils.js"></script>
<script src="js/libraries/underscore.js"></script>
<script src="js/controllers/VideoListCtrl.js"></script>
<script src="js/filters/CategoryFilter.js"></script>
<script src="js/filters/ArticleFilter.js"></script>
<script src="js/angular/dirPagination.js"></script>
</body>
</html>
Controller:
var videoApp = angular.module('videoApp', ['videoAppFilters', 'ui.unique', 'angularUtils.directives.dirPagination']);
videoApp.controller('VideoListCtrl', function ($scope, $http, $filter) {
$http.get('http://academy.tutoky.com/api/json.php').success(function (data) {
$scope.videos = data;
$scope.categories = $filter('categoryFilter')(data);
});
$scope.getFilteredResults = function (category, data) {
$scope.videos = $filter('articleFilter')(category, data);
return $scope.videos;
};
});
Article filter:
angular.module('videoAppFilters').filter('articleFilter', function () {
return function (category, data) {
var filteredData = [];
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].categories.length; j++) {
if (data[i].categories[j] == category) {
filteredData.push(data[i]);
}
}
}
return filteredData;
};
});
Categories are filtered with unique filter and after loading page everything works. But, I' want to filter articles by category after clicking on category name.
So when i click on Handball for example, it should show me only results that have Handball category.
But, when i click on category name, angular throw exception about duplicates. I don't really understand why its able to handle them with unique on first load but after model changes, it's not.
Any suggestions please?

Ok, I solved this. There were 2 problems, one was that I needed to get rid of duplicates again after rewriting that $scope.videos, because the second time unique filter in categories in did not proceed ( dunno why ).
I did it like this:
$scope.getFilteredResults = function (category, data) {
$scope.videos = $filter('articleFilter')(category, data);
return $scope.videos;
};
and add unique to videos ng-repeat like
<article class='col-lg-3 col-md-4 col-sm-12 col-xs-12 video' dir-paginate="video in videos | unique | itemsPerPage: 12">
Another problem was that I was rewriting $scope.videos so after every filtration there were less and less results, cause it was filtered over and over again. I had to create another variable that was working as source of data but were not rewritten.
So instead of
$scope.videos = data;
I have
$scope.videos = data;
$scope.allData = data;
Also I had to change the onClick action to pass allData instead of videos
<li ng-repeat="category in categories"> {{category}}</li>

Related

Local undefined 404 when doing API call

This project is using the cocktail api to search for a specific ingredient (think gin or vodka) and then return all the drinks that contain the ingredient. I was able to get the results to display, but I wanted the thumbnail pic of the drink (included in the api as strDrinkThumb). When I try to get the pictures to display I get the follow error:
GET http://local/undefined 404 (Not Found)
window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM fully loaded and parsed');
});
let ingredients = document.getElementById('ingredients');
let searchTerm= document.getElementById('search-Bar');
let searchBtn = document.getElementById('searchBtn');
let drinkInfo = document.getElementById('drinkInfo');
let ingredientList = []
searchBtn.addEventListener("click", async (e) => {
const searchString = searchTerm.value.toLowerCase();
fetch(`https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=${searchString}`)
.then((response) => response.json())
.then((filteredIngredients) => {
displayIngredient(filteredIngredients.drinks);
})
.catch((error) => {
});
});
function displayIngredient(drinkData){
const ingredients = [];
//maps over array and makes new array
drinkInfo.innerHTML = drinkData.map( ({strDrink}) => { //destructuring
//use backticks and html
return` <div> //use backticks and html
<div class="card" style="width: 14rem;">
<div class="card-body">
<h5 class="card-title">${strDrink} </h5>
<img src="${drinkData.strDrinkThumb}"/>
</div></div>
`; //use backticks and html
}).join('');
drinkInfo.appendChild(drinkInfo);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Cocktail App</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<input type="text" id="search-Bar" placeholder="Enter main ingredient..."/>
<button id="searchBtn">search</button>
</header>
<div class="drinkInfo" id="drinkInfo">
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<script type="text/javascript" src="./extrafile.js"></script>
</body>
</html>
In drinkData.map function you are only pulling strDrink value from the object, you need also get strDrinkThumb
Then you are trying get strDrinkThumb from drinkData which is an array, not an object.
Try this:
drinkInfo.innerHTML = drinkData.map( ({strDrink, strDrinkThumb}) => { //destructuring
//use backticks and html
return` <div> //use backticks and html
<div class="card" style="width: 14rem;">
<div class="card-body">
<h5 class="card-title">${strDrink} </h5>
<img src="${strDrinkThumb}"/>
</div></div>
`; //use backticks and html
}).join('');

System.Data.Entity.DynamicProxies foreach

I've tried to loop out every "category" there is in my database, and put it into the dropdown, but instead it gives me a long code starting of with this:
System.Data.Entity.DynamicProxies
I'm not entirely sure why? And how to fix it. At first i thought it was due to me not having the "categories" in the same model, but as i joined it in the same model, nothing really seemed to change.
So I've tried to search around the internet, but I couldn't seem to find something that resembled the problem that i had.
So I want to know, whats causing it, and what kind of solutions are available in this case scenario?
What i tried to do:
Loop out the categories from the database into the dropdown menu so that all the categories were shown, without typing them in the html _layout file.
Heres my code:
function dropFunction() {
document.getElementById("inDrop").classList.toggle("show");
}
window.onclick = function (event) {
if (!event.target.matches('.dropBtn')) {
var dropdowns = document.getElementsByClassName("dropCon");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
#model Fisk.Models.ALL
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title</title>
<link href="~/Content/css/Common.min.css" rel="stylesheet" />
<link href="~/Content/css/bootstrap.min.css" rel="stylesheet" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-8">
<h2>Fisk.nu</h2>
</div>
<div class="col-lg-4">
<form action="/" method="post">
<input type="text" name="name" value="" class="col-md-8" />
<input type="button" name="name" value="Søg" class="col-md-3" />
</form>
</div>
</div>
<ul id="navMenu">
<li>Forsiden</li>
<li class="dropdown">
<button onclick="dropFunction()" class="dropBtn">Produkter</button>
<ul id="inDrop" class="dropCon">
#foreach (var item in Model.Kategorier)
{
<li class="dropList">#item</li>
}
</ul>
</li>
</ul>
#RenderBody()
<footer>
<p>Fisk.nu, Silovej 2, DK-8000 Århus C, Tlf. +45 87 11 12 13, info#fisk.nu</p>
</footer>
</div>
<script src="~/Content/js/bootstrap.min.js"></script>
<script src="~/Content/js/jquery-3.3.1.min.js"></script>
<script src="~/Content/js/Slider.js"></script>
<script src="~/Content/js/Dropdown.js"></script>
</body>
</html>
Heres the Home Controller:
public ActionResult Index()
{
var ViewModel = new Fisk.Models.ALL();
ViewModel.tekstBoks = db.front_TekstBoks.ToList();
ViewModel.Slider = db.front_Slider.ToList();
ViewModel.Kontakt = db.web_Kontakt.FirstOrDefault();
ViewModel.Kategorier = db.site_Kategorier.ToList();
List<front_Slider> sliders = new List<front_Slider>();
List<front_TekstBoks> tekstBoks = new List<front_TekstBoks>();
List<site_Kategorier> kategorier = new List<site_Kategorier>();
return View(ViewModel);
}
You have to access a property of the entity in your collection Kategorier -> Kategori, like #item.Name or something, Otherwise you're just printing the result of ToString()
<ul id="inDrop" class="dropCon">
#foreach (var item in Model.Kategorier)
{
<li class="dropList">#item.Name</li>
}
</ul>

KO "click" binding won't work for mobile device responsive

I am trying to create a responsive one page web application. On clicking the list of items on the side bar you the markers and on the map should animate and display info window. It seems to be working perfect on normal browser layout but when I toggle display to smaller screens or on a mobile device, The click function does not work. The logic seems to be correct. Please help me understand where I am going wrong and what I should do. Thank you.
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="style.css" rel="stylesheet">
<script src="js/jquery-3.2.1.js"></script>
<script src="js/knockout-3.4.0.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div id="sidebar" class="col-xs-12 col-sm-5 col-md-3">
<h1 class="center" > Chennai City Culture </h1>
<div class="input-group col-xs-12 col-sm-6 col-md-12" >
<input id="text-search" type="text" class="form-control" placeholder="Enter here" data-bind="textInput: query">
</div>
<div class= "list-box" data-bind="foreach: filteredItems">
<hr>
</div>
</div>
<div class="col-xs-16 col-sm-6 col-md-8">
<div id="map">
</div>
</div>
</div>
</div>
<script src="js/app.js"></script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBf9eFadPLrD3QIQT7ygrYN8aRO5YuAUyE&callback=initMap" onerror="error()">
</script>
</body>
</html>
JS:
function appViewModel(){
var self = this;
this.query = ko.observable('');
this.locationArray = ko.observableArray([]);
locations.forEach(function(item){
self.locationArray().push(item);
});
self.setLoc = function(clickedLoc) {
var clickedData = clickedLoc.marker;
google.maps.event.trigger(clickedData, 'click');
};
self.filteredItems = ko.computed(function(){
var filter = self.query().toLowerCase();
if(!filter){
for (i = 0; i < locations.length; i++) {
if (locations[i].marker) //checks to see that markers exist
locations[i].marker.setVisible(true);
}
return self.locationArray();
}
return this.locationArray().filter(function (item){
var passedFilter = item.title.toLowerCase().indexOf(filter) > -1;
item.marker.setVisible(passedFilter);
return passedFilter;
});
}, self);
}
ko.applyBindings(new appViewModel());
click events aren't the same as touch events; try including a library like touchpunch that will handle those events for you for mobile devices. I had the same issue with a KO app I was building and that seemed to solve it.

$http GET not showing in display in AngularJS

I am creating an app in AngularJS, where I am grabbing the data from the backend to display on the view. But, for some reason, I am getting the data in my console but not in my view. I will be so thankful if any one can help me solve this. Thanks in advance.
Here is my code. -Services
app.factory('user', ['$http', function($http) {
var userInfo = {
getUserInfo: function () {
return $http.get('https://************/*****/**/***********')
}
};
return userInfo;
}]);
home page(view)
<div class="users" ng-repeat="user in users | filter:userSearch" >
<a href="#/users/{{ user.id }}">
<img ng-src="{{user.img}}"/>
<span class="name">{{user.first}} </span>
<span class="name">{{user.last}} </span>
<p class="title">{{user.title}} </p>
<span class="date">{{user.date}} </span>
</a>
HomeController
var isConfirmed = false;
app.controller('HomeController', function($scope, user, $http) {
if (!isConfirmed) {
user.getUserInfo().then(function (response) {
$scope.userInfo = response.data;
isConfirmed = $scope.userInfo;
console.log($scope.userInfo);
}, function (error) {
console.log(error)
});
}
});
App.js
var app = angular.module("Portal", ['ngRoute']);
app.controller('MyCtrl', function($scope) {
$scope.inactive = true;
$scope.confirmedAction = function() {
isConfirmed.splice($scope.person.id, 1);
location.href = '#/users';
}
});
index.html
<!doctype html>
<html ng-app="Portal">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://code.angularjs.org/1.2.28/angular-route.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,300,700' rel='stylesheet' type='text/css'>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="css/main.css" rel="stylesheet" />
</head>
<body>
<div class="header">
<div class="container">
<h3>Portal</h3>
</div>
</div>
<div class="main">
<div class="container">
<div ng-view>
</div>
</div>
</div>
<!-- Modules -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/HomeController.js"></script>
<script src="js/controllers/UserController.js"></script>
<!-- Services -->
<script src="js/services/users.js"></script>
</body>
</html>
change your ng-repeat="user in users" to ng-repeat="user in userInfo"
as your assigning and consoling only $scope.userInfo in your controller
The property you assign data has to be same as of binded to view.
As per your HTML data should be in users. So do it like : $scope.users = response.data;.
or if you assign data to userInfo, then bind it on html. like :
<div class="users" ng-repeat="user in userInfo | filter:userSearch" >

ng-click works kind of

I am learning angular js right now and have hit another rut. I am trying to make my buttons change the movie ID. I know it is recognizing the click because I had it change some words in the HTML file to test it. I think it isn't talking to my JS file.
I found this during my search http://jsfiddle.net/7Sg6a/. The docs just have an expression inside the parenthesis and this example has parameters. I tried both and a few other but neither worked.
Here is my latest failed attempt. If I could get a nudge in the right direction I would be very grateful.
<!DOCTYPE HTML>
<html lang = "en" ng-app="movies"><!-- lets page use controllers/movies.js-->
<head>
<title>Watch a movie!</title>
<meta charset = "UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="description" content="">
<meta name="keywords" content="">
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://www.mysite.com/rss/rss2.xml" />
<link href="css/bootstrap.css" rel="stylesheet" type="text/css">
<link href="css/style.css" rel="stylesheet" type="text/css">
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet">
<!-- <link href="css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css"> -->
<!-- Preloading scripts? -->
<script src="js/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.0rc1/angular-route.min.js"></script>
<!--<script src="js/angular-resource.min.js" type="text/javascript"></script>-->
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<!-- <script src="js/bootstrap.js"></script> -->
<script src="controllers/movies.js"></script>
</head>
<body>
<div id="wrapper">
<header>
<div id="logo">
<img src="images/logo.png" alt="Cinema Plus - Movies plus a whole lot more." class="img-responsive">
</div>
</header>
<nav>
<div class='row-fluid'>
<div class="span2"></div>
<button ng-click="nowShowing()" type="button" class="btn btn-primary btn-lg span4 "><h3>NOW PLAYING</h3></button>
<button ng-click="comingSoon()" type="button" class="btn btn-default btn-lg span4 "><h3>COMING FRIDAY</h3></button>
<div class="span2"></div>
</div>
</nav>
<div id='content' class='row-fluid'>
<div class='span8 info'>
<h2 ng-controller = "movieController">{{movies.title}}</h2>
<h2 ng-controller = "movieController">RATED: {{movies.mpaa_rating}}</h2>
<h2 ng-controller = "movieController">{{movies.runtime}} Minutes</h2>
<p ng-controller = "movieController">DESCRIPTION: {{movies.synopsis}}</p>
</div>
<div class='span4 poster'>
<img ng-controller = "movieController" src={{movies.posters.original}} alt={{movies.title}} class="img-responsive">
</div>
</div>
<div>
Note: This theator only plays one movie at a time. film will be hard coded into the app. Would like to see it fed by RSS orsomething in the future.
</div>
</div> <!-- END WRAPPER -->
</body>
</html>
JS
var movies = angular.module('movies', []);
movies.controller('movieController', function ($scope, $http) {
$http.jsonp('http://api.rottentomatoes.com/api/public/v1.0/movies/771303861.json', {
params: {
apikey: 'wq98h8vn4nfnuc3rt2293vru',
callback: 'JSON_CALLBACK'
}
})
.success(function (data) {
$scope.movies = data;
});
});
movies.click('nowShowing', function ($scope){
alert("asdasd");
});
how long until I actually get this and can stop asking stupid questions?
your .click function doesn't belong. You're using Angular like jQuery, and it's more (awesome) than that. You need to put the nowShowing function and such inside your controller:
var movies = angular.module('movies', []);
movies.controller('movieController', function ($scope, $http) {
$http.jsonp('http://api.rottentomatoes.com/api/public/v1.0/movies/771303861.json', {
params: {
apikey: 'secret',
callback: 'JSON_CALLBACK'
}
})
.success(function (data) {
$scope.movies = data;
});
$scope.nowShowing = function(){
//whatever is in here will execute when a user interacts with an element with the ng-click="" directive
}
});
Also, I would highly recommend you create a service for your http requests to your api. You are creating a tightly coupled app with your current approach.
movies.factory('moviedata',function($http){
return
$http.jsonp('http://api.rottentomatoes.com/api/public/v1.0/movies/771303861.json', {
params: {
apikey: 'secret',
callback: 'JSON_CALLBACK'
}
})
})
then 'inject' it in your controller like so:
movies.controller('movieCtrl',function($scope, moviedata){
//resolve returned promise
moviedata.success(function(data){
$scope.data = data;
});
$scope.nowShowing = function($log){
//whatever is in here will execute when a user interacts with an element with the ng-click="" directive
$log.info("nowShowing method fired");
}
})

Categories