Cannot read property 'toLowerCase' of undefined angularjs - html

I'm trying to make a search function in my angularjs "webapp". When I search in products all works fine, but when I change everything so that it searches into users, i get an error Cannot read property 'toLowerCase' of undefined.
Here's my js:
return function(arr, searchString){
if(!searchString){
return arr;
}
var result = [];
searchString = searchString.toLowerCase();
angular.forEach(arr, function(item){
if(item.title.toLowerCase().indexOf(searchString) !== -1){
result.push(item);
}
});
return result;
};
});
And here's the html that's calling it:
<div ng-controller="userCtrl" class="container-app">
<div class="bar">
<input type="text" class="search" ng-model="searchString" placeholder="Enter your search terms" />
</div>
<div class="searchResultsText">
<h2>Zoekresultaten: </h2>
</div>
<div class="searchResults" ng-repeat="user in users | searchFor:searchString">
<a class="normal" href="#">{{user.name}}</a>
</div>
it does show me the list of users, just as soon as I start typing in the search bar it gives me the error.
when I use the exact same function, with a different controller it works. Here are the 2 controllers:
app.controller('customersCtrl', function ($scope, $http) {
$http.get(apiUrl + "product/list")
.success(function (response) {
$scope.products = response;
});
});
app.controller('userCtrl', function ($scope, $http) {
$http.get(apiUrl + "user/list")
.success(function (response) {
$scope.users = response;
});
});
so basically customerCtrl works fine, but when i change values to userCtrl it stops working.
any suggestions?

Most likely item.title is at least once undefined.
return function(arr, searchString){
if(!searchString){
return arr;
}
var result = [];
searchString = searchString.toLowerCase();
angular.forEach(arr, function(item){
if(
angular.isDefined(item.title) &&
item.title.toLowerCase().indexOf(searchString) !== -1
){
result.push(item);
}
});
return result;
};

Related

My log in code seem not working properties

I want to get the file from json and compare them with the textbox that I get from the input form, but my code seems not working properties. I am very new to angular and this is my first try project not for work.
//This is JS file
(function () {
'use strict';
angular.module('routerApp').controller('LoginCtrl', function ($http, $scope, $location) {
$scope.loginUser = function () {
$http.get('data.json').then(function(data){
$scope.users = data;
var usr = $scope.usr;
var pwd = $scope.pwd;
if(data.username == usr && data.password == pwd){
$location.path('/laptop');
}
else{
alert("Username or password is incorrect");
}
});
};
});
})();
When I click login button it always true even I didn't input anything

Angular service not storing data between two controllers

I am trying to use a service to set title in controller1 and then access title in controller2.
sharedProperties.setTitle(title) works in controller1, but when I try to get the title in controller2, it gets "title" (the initial value) instead of the new value.
I've also tried storing title in an object but it didn't work.
app.service('sharedProperties', function () {
var title = "title"
return {
getTitle: function () {
return title;
},
setTitle: function (val) {
title = val;
}
}
});
app.controller('controller1', ['$scope', 'sharedProperties', function ($scope, sharedProperties) {
$('body').on("click", "button[name=btnListItem]", function () {
// gets the title
var title = $(this).text();
// sets the title for storage in a service
sharedProperties.setTitle(title);
});
}]);
app.controller('controller2', ['$scope', 'sharedProperties', function ($scope, sharedProperties) {
$scope.sharedTitle = function() {
return sharedProperties.getTitle();
};
}]);
And in my view, I have {{ sharedTitle() }} which should, as I understand it, update the title text with the new title.
Also, in case this is relevant: the two controllers are linked to two different html pages.
What am I doing wrong?
EDIT
Updated button listener:
$('body').on("click", "button[name=btnListItem]", function () {
// gets the text of the button (title)
var title = $(this).text();
sharedTitle(title);
alert(sharedProperties.getTitle());
document.location.href = '/nextscreen.html';
});
$scope.sharedTitle = function (title) {
sharedProperties.setTitle(title);
};
It seems to be correct in your sample code. I setup jsfiddle and it seems work correctly. Finding out a difference between my jsfiddle and your actual code would help you to find the problem you should solve.
Javascript:
angular.module('testapp', [])
.service('sharedProperties', function(){
var title = 'title';
return {
getTitle: function(){
return title;
},
setTitle: function(val){
title = val;
}
};
})
.controller('controller1', function($scope, sharedProperties){
$scope.change_title = function(newvalue){
sharedProperties.setTitle(newvalue);
};
})
.controller('controller2', function($scope, sharedProperties){
$scope.sharedTitle = function(){
return sharedProperties.getTitle();
};
})
Html:
<div ng-app="testapp">
<div ng-controller="controller1">
<input ng-model="newvalue">
<button ng-click="change_title(newvalue)">Change Title</button>
</div>
<div ng-controller="controller2">
<span>{{sharedTitle()}}</span>
</div>
</div>
My jsfiddle is here.
You have to print console.log(sharedProperties.getTitle()); Dont need return from controller.
So your code of controller2 is $scope.sharedTitle = sharedProperties.getTitle();
You need to use the $apply so that angular can process changes made outside of the angular context (in this case changes made by jQuery).
$('body').on("click", "button[name=btnListItem]", function () {
// gets the title
var title = $(this).text();
// sets the title for storage in a service
$scope.$apply(function() {
sharedProperties.setTitle(title);
});
});
See plunker
That said, this is BAD PRACTICE because you're going against what angular is meant for. Check “Thinking in AngularJS” if I have a jQuery background?. There are cases when you need to use $apply like when integrating third party plugins but this is not one of those cases.

Accessing Controller variable in ng-repeat in AngularJS

I am pretty new to web development and I have been working on a small project.
This is what I am trying to achieve. I have a badly nested JSON data for 10 products. This is the data I am using.
I have a "View More" button for each product for its specifications. The specifications can be accessed using the index as such "products[index].ProductInfo.p_product_specs.Value". When I click on the "view more" button, I am routing to a different page viewmore.html. In the viewmore.html, I have this html code
<div ng-controller='mainController'>
<div class="viewMore">
<ul ng-repeat="spec in products[id].ProductInfo.p_product_specs.Value">
{{ spec.Key }} : {{ spec.Value}}
</ul>
</div>
</div>
I have a function in the controller which return me the index of that product in the array "products" as soon as I click on the "View More" button.
$scope.viewmorefn = function(){
var self = this;
$scope.id = (function() {
//some code which returns index, console.log gives correct results.
return index;
}
)();
}
But when I try to use "id" in the ng-repeat (in viewmore.html), it just doesn't work. Is there any way I can make "id" accessible in my viewmore.html page? Any help will be greatly appreciated, I have already given this 2 days. Thanks.
EDIT : #uowzd01 : I am not sure if the data is being lost. The controller has this:
$http.get(url)
.success(function (result) {
$scope.products = result.ProductsList;
})
.error( function (data, status) {
console.log("Error retrieving data");
});
And in the viewmore.html I am able to interpolate "{{ products }}" and {{ products[0].ProductInfo.p_product_specs.Value }} and also the data of other objects if I specify the index explicitly.
EDIT 2: Complete code
HTML : First Page : product_list_page.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="assets/css/reset.css" />
</head>
<body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript"></script>
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.0/angular-route.min.js"></script>
<script src="app.js"></script>
<div class="main">
<div ng-view></div>
</div>
</body>
</html>
home.html
<div ng-controller='mainController'>
<div class="showProduct">
<div ng-show="isShow" ng-mouseenter="isShow=true">
<show-repeat></show-repeat>
</div>
</div>
<div class="eproducts" ng-repeat="product in products">
<div class="fixed-size-square" ng-mouseenter="hoverIn()">
<show-products></show-products>
</div>
</div>
</div>
viewmore.html
<div>
<div class="viewMore">
<ul ng-repeat="spec in products[selfId].ProductInfo.p_product_specs.Value">
<li> {{ spec.Key }} : {{ spec.Value}} </li>
</ul>
</div>
</div>
JavaScript code :
var myApp = angular.module('myApp', ['ngRoute']);
myApp.controller('mainController', ['$scope', '$window', '$filter', '$http', function($scope, $window, $filter, $http){
$http.get('data.txt')
.success(function (result) {
$scope.products = result.ProductsList;
})
.error( function (data, status) {
console.log("Error retrieving data");
});
$scope.hoverIn = function() {
$scope.isShow = true;
$scope.pr = this;
$scope.price = this.product.ProductInfo.p_product_price;
}
$scope.hoverOut = function() {
$scope.isShow = false;
}
$scope.returnPrice = function() {
$window.alert('The price is $' + $scope.price);
}
$scope.viewmorefn = function(){
var self = this;
$scope.selfId = (function() {
var count = 0;
var str1 = self.product.ProductInfo.Brand + self.product.ProductInfo.p_product_description;
for ( var i = 0 ; i < $scope.products.length ; i++)
{
var str2 = $scope.products[i].ProductInfo.Brand + $scope.products[i].ProductInfo.p_product_description;
if(str1 === str2)
break;
count = count + 1;
}
return count;
}
)();
console.log('id is : ' +$scope.selfId);
}
}]);
myApp.directive("showRepeat", function(){
return {
template : '<img class="lgImage" src="{{ pr.product.imageURLs.lg }}"> <br / > <div class="descText"> {{ pr.product.ProductInfo.Brand }} {{ pr.product.ProductInfo.p_product_description }} <br /> <div class="divClass"> <ul class="descList" ng-repeat="spec in pr.product.ProductInfo.p_product_specs.Value | newFilter"> <li> {{ spec.Key }} </li> </ul> </div> </div> <span class="priceText"> {{ product.ProductInfo.p_product_price | currency }} <br /> </span> <button id="cartBtn" ng-click="returnPrice()">Add to Cart</button> <br /> <div class="priceTop">{{ pr.product.ProductInfo.p_product_price | currency }} </div>'
}
});
myApp.directive("showProducts", function(){
return {
template : '<div class="prdList"><br /><img class="showprdimg" src="{{ product.imageURLs.sm }}"><br /><br/> <div class="spanText">{{ product.ProductInfo.Brand }} {{ product.ProductInfo.p_product_description }} </div> <br /><br/> <div class="priceText">{{ product.ProductInfo.p_product_price | currency }} </div><br/>"<button id="viewMoreBtn" ng-click="viewmorefn()">View More</button></div>'
}
});
myApp.filter('newFilter', function(){
return function(newSpec) {
var out = [];
angular.forEach(newSpec, function (newSpec) {
if((newSpec.Key === 'ENERGY STAR Qualified') && (newSpec.Value ==='Yes')) {
out.push(newSpec);
}
});
return out;
}
});
myApp.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'home.html',
controller : 'mainController'
})
// route for the view more page
.when('/viewmore', {
templateUrl : 'viewmore.html',
controller : 'mainController'
})
});
Plunker Demo
First, to clear some of the dust - though it is not the specific problem, you are instantiating the same controller numerous times - in your HTML and ngRoute. Pick one, not both. I got rid of the ng-controller directives in your HTML, so it just uses ngRoute now. However, because you are calling the same controller for both views, the controller is losing it's values because you are getting a new instance of the controller. It is also fetching the same data twice. While it technically is working, it's really bad JavaScript. You should look at ui-router and do some nested views and instantiate the controller one time and fetch the data one time.
To get it working, I essentially created a service to store the index value in:
myApp.factory('theIndex', function() {
return {
val: ''
}
})
When the controller loads, it pulls whatever value is stored in the service, and when you click the View More button, it stores the index value in the service.
myApp.controller('mainController', ['$scope', '$window', '$filter', '$http', 'theIndex', function($scope, $window, $filter, $http, theIndex){
$scope.selfId = theIndex.val; // get whatever index value is stored, if any
//... buncha stuff
$scope.viewmorefn = function(){
var self = this;
$scope.selfId = (function() {
var count = 0;
var str1 = self.product.ProductInfo.Brand + self.product.ProductInfo.p_product_description;
for ( var i = 0 ; i < $scope.products.length ; i++)
{
var str2 = $scope.products[i].ProductInfo.Brand + $scope.products[i].ProductInfo.p_product_description;
if(str1 === str2)
break;
count = count + 1;
}
return count;
}
)();
theIndex.val = $scope.selfId // set the index value here
console.log('id is : ' +$scope.selfId);
}
}]);
The plunker provided is updated, using all your supplied code. Don't forget to inject the new service into your controller. This should get you up and running, though as I said before, it's pretty ugly.

give random order to $http json oject through angular JS controller

I pull in a JSON object with my controller below, but how do I make the order random, on each page refresh?
app.controller('MainCtrl', ['$scope', '$http', 'makeRandom', function ($scope, $http, makeRandom) {
$http.get('projects/projects.json').success(function(data) {
$scope.works = data;
});
makeRandom.forEach($scope.works, function(work) {
work.rank = Math.random();
});
}]);
template.html
<section ng-repeat="work in works | orderBy:'rank'" class="showcase {{work.class}}">
...
</section>
You pretty much have all the work done, you just need to put it together:
This is based off your work:
app.controller('myCtrl', ['$scope', '$http', function($scope, $http){
$http.get('projects/projects.json').success(function(data) {
$scope.works = data;
}).error(function(){
// works on error response because I don't have your code, just copy this to success response
// here I just generate a list of ids and then randomize them
var works = [];
for(var i=0; i< 20; i++){
works.push({id: i});
}
$scope.works = makeRandom(works);
});
function makeRandom(inputArray){
angular.forEach(inputArray, function(value){
value.rank = Math.random();
});
return inputArray;
}
}]);
HTML:
<section ng-repeat="work in works | orderBy:'rank'" class="showcase {{work.class}}">
{{work.rank}} {{work}}
</section>
Here is a working example: http://plnkr.co/edit/xIwD0zWdodnYSIupm1va?p=preview

clearInterval() not working after stop button click

i am trying to Refresh div using java script . setInterval() and clearInterval (), its working fine, but i want stop Refresh process for single div when i clicked stop button ..clear Interval not working herer
<script type ="text/javascript">
$(document).ready(function () {
$('.output').click(function () {
var id = $(this).closest('.g').attr('id');
Go(id);
})
$('.bt').click(function () {
var id = $(this).closest('.g').attr('id');
stop(id)
});
function Go(id) {
id = setInterval(function () {
Chat_msg('Ch04', id, u)
}, 3000);
};
function stop(id) {
clearInterval(id);
}
})
</script>
</head>
<body>
<div id="a" class='g'>
<div class="output"></div>
<input id="Button1" type="button" value="stop" class="bt" />
</div>
<div id="b">
<div class="output"></div>
<input id="Button2" type="button" value="stop" class="bt"/>
</div>
<div id="c">
<div class="output"></div>
<input id="Button3" type="button" value="stop" class="bt" />
</div>
</body>
</html>
Use a global variable for your interval.
var interv = null;
interv = setInterval(function { ... }, 5000);
$('#btn').on('click', function(){
if (interv) clearInterval(intev);
})
It's likely the reference you associated with setInterval is not within the scope of your stop-button handler.
$("#start").on("click", function(){
var interv = setInterval(function(){ /*...*/ }, 1000);
});
$("#stop").on("click", function(){
clearInterval(interv);
});
In the code above, our interv variable is not within the scope of our #stop button handler. We could change this by moving it up another level:
var interv;
$("#start").on("click", function(){
interv = setInterval(function(){ /*...*/ }, 1000);
});
$("#stop").on("click", function(){
clearInterval(interv);
});
Now both handlers have access to the interv variable.
Looks like a combination of a scoping issue, and interchangeably using id DOM attributes with setInterval response values.
<script type ="text/javascript">
$(document).ready(function () {
var timeouts = {};
$('.output').click(function () {
var id = $(this).closest('.g').attr('id');
go(id);
});
$('.bt').click(function () {
var id = $(this).closest('.g').attr('id');
stop(id);
});
function go(id) {
timeouts[id] = setInterval(function () {
Chat_msg('Ch04', id, u)
}, 3000);
}
function stop(id) {
clearInterval(timeouts[id]);
}
});
</script>
The way I have gone about this in the past is using a function that uses a set timeout to call itself.
var stop = false
function caller () {
if (stop === true){
//do something
setTimeout(caller() , 1000);
}
else{
//do something after button has been click and stop is set to true
}
}