MEAN Stack Get Username from UserId forEach row - javascript

I'm trying to get the user data (such as username) for each user on a row of reviews. I kept my user information (login credentials on another model/controller), so is there a way to access and show the username on the view?
Below is my JSON code:
{
"_id": "56873fc9182b3741059357d0",
"longitude": 113.83507800000007,
"latitude": 22.1533884,
"location": "Hong Kong",
"name": "Hong Kong",
"__v": 0,
"category": "Attraction",
"reviews": [
{
"comment": "Add the comment to the form",
"rating": 3.5,
"userId": 11,
"review_id": "44NL7kkwhy72"
},
{
"comment": "Hello test",
"rating": "3.4",
"userId": "56809c0cf0a264b101a1dd61",
"review_id": "jN7f1iFlQVha"
},
{
"comment": "Hello test ty",
"rating": "3.7",
"userId": "56863c8f2959b4c601fbd9eb",
"review_id": "QcJpw4yopF1q"
}
]
},
//view all reviews for a location
.controller('AllReviews', function($scope, $stateParams, LocFac, UserFac) {
id = $stateParams.id;
LocFac.getLocation(id).then(function(data) {
$scope.locations = data.data;
$scope.reviews = data.data.reviews;
//variables to show information on location reviews
$scope.lengthrev = (data.data.reviews).length;
$scope.locationname = data.data.name;
//addition of values and retrieve the value
$scope.getTotal = function(){
var total = 0;
for(var i = 0; i < $scope.lengthrev; i++){
var review = $scope.reviews[i];
User.getUser(review).then(function(datat) {
$scope.locun = datat.username;
});
total += review.rating;
}
return total;
}
grandtotal = $scope.getTotal();
//get average of all values \
$scope.averagereviews = grandtotal/($scope.lengthrev);
});
})
My location reviews view
<ion-view view-title="All Reviews" class="all_reviews">
<ion-content class="all_reviews">
<h3>{{ locationname }}</h3>
<h3>Average Rating: {{ averagereviews }} <ng-rate-it name="rating" ng-model="averagereviews" resetable="false" read-only="true"></ng-rate-it>/ {{ lengthrev }} Reviews </h3>
<ion-list>
<ion-item data-ng-repeat="location in locations.reviews">
<ng-rate-it name="rating" ng-model="location.rating" resetable="false" read-only="true"></ng-rate-it>
{{ location.userId }}
<h4>{{ location.review_id }}</h4>
<h4>{{ location.comment }}</h4>
</ion-item>
</ion-list>

Considering your two aysnc operations,(one to fetch reviews and another one to fetch usernames) I think this approach will be more suitable.
First fetch the reviews.
Display the reviews.
While displaying the reviews use the UserFac to fetch the username asynchronously using ng-init directive.
I have created a demo plunker as an example with the sample data you provided in question.
Example:
Demo Plunker
app.js
var app = angular.module("app", []);
app.factory('LocFac', function($http) {
var factory = {};
factory.getLocation = function(id) {
return $http({
method: 'GET',
url: 'data.json'
});
}
return factory;
});
app.factory('UserFac', function($http) {
var factory = {};
factory.getUser = function(id) {
return $http({
method: 'GET',
url: 'user.json'
});
}
return factory;
});
app.controller('AllReviews', function($scope, LocFac, UserFac) {
$scope.show = false;
$scope.testClick = function() {
id = "56873fc9182b3741059357d0";
LocFac.getLocation(id).then(function(data) {
$scope.reviews = data.data.reviews;
$scope.lengthrev = (data.data.reviews).length;
$scope.show = true;
});
}
$scope.getUserName=function(review) {
UserFac.getUser(review.id).then(function(user) {
review.userName=user.data.userName;
review.showUserName=true;
});
}
})
HTML:
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="AllReviews">
<button ng-click="testClick()">Click here</button>
<ul ng-show="show" ng-repeat="review in reviews track by $index" ng-init="getUserName(review)">
{{review | json : spacing}}
<p ng-show="review.showUserName">
{{review.userName}}
</p>
</ul>
</body>
</html>
Explanation:
While iterating the review array in ng-repeat,we pass the review object to the UserFac service to fetch the userName.This service will set the name inside the review object itself.

Related

Adding objects to array in service

i've tried to add an object to my array savedTemplates in a service with the function getTemplates.
I've used a service for this in order to access the templates in multiple views.
Unfortunately, if i try to call my function, nothing happens.
services.js:
.factory('templateData', function(){
var savedTemplates = [
{"name":"Adam Müller", "iban":"AT29100020003000","image":"adam.jpg"},
{"name":"Ben Streicher","iban":"AT34900080007000","image":"ben.png"},
{"name":"Max Krossmann","iban":"AT23400050006000","image":"max.png"}
];
var getTemplates = function(){
return savedTemplates;
};
var addTemplates = function(insertName,insertIban){
savedTemplates.push=({"name": insertName, "iban": insertIban, "image": 'mike.png'});
alert("This is savedTemplates:" + savedTemplates);
};
return {
getTemplates:getTemplates,
addTemplates:addTemplates
};
})
template-save.html:
<button class="button button-large button-positive" ng-click="addTemplates(newreceiver,newiban)" ui-sref="tab.templates">
Speichern
</button>
I would be very grateful for any help, since I'm quite desperated already.
Here is a sample snippet.
You also have a problem in your factory addTemplates code, you should use savedTemplates.push ({ ... }], not savedTemplates.push = ({ ... }]
Snippet
angular.module('app', []);
angular.
module('app')
.controller('ExampleController', ['$scope', 'templateData', function($scope, templateData) {
$scope.addTemplates = templateData.addTemplates;
}])
.factory('templateData', function() {
var savedTemplates = [{
"name": "Adam Müller",
"iban": "AT29100020003000",
"image": "adam.jpg"
},
{
"name": "Ben Streicher",
"iban": "AT34900080007000",
"image": "ben.png"
},
{
"name": "Max Krossmann",
"iban": "AT23400050006000",
"image": "max.png"
}
];
var getTemplates = function() {
return savedTemplates;
};
var addTemplates = function(insertName, insertIban) {
savedTemplates.push ({
"name": insertName,
"iban": insertIban,
"image": 'mike.png'
});
console.log("This is savedTemplates:" + JSON.stringify(savedTemplates, null, 2));
};
return {
getTemplates: getTemplates,
addTemplates: addTemplates
};
});
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="ExampleController">
<button ng-click="addTemplates('Marty McFly', 'BTTF900080007000')">
Speichern
</button>
</body>
</html>

Obtaining a JSON array from PHP via JavaScript in the Ionic framework

I am trying to to get a JSON array from a server side PHP file. I have the PHP set up to query a MySQL database and return the result as a JSON array. I'm using the ionic framework to develop an app. At the moment I have the app working with a hard coded JSON array, this is what needs to be replaced by the array gained from the PHP.
This is the file where the chats variable should contain the JSON array from the PHP file.
angular.module('starter.services', [])
.factory('Chats', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var chats = [{
id: 0,
name: 'Ben Sparrow',
lastText: 'You on your way?',
face: 'img/ben.png'
}, {
id: 1,
name: 'Max Lynx',
lastText: 'Hey, it\'s me',
face: 'img/max.png'
}, {
id: 2,
name: 'Adam Bradleyson',
lastText: 'I should buy a boat',
face: 'img/adam.jpg'
}, {
id: 3,
name: 'Perry Governor',
lastText: 'Look at my mukluks!',
face: 'img/perry.png'
}, {
id: 4,
name: 'Mike Harrington',
lastText: 'This is wicked good ice cream.',
face: '/img/mike.png'
}];
return {
all: function() {
return chats;
},
remove: function(chat) {
chats.splice(chats.indexOf(chat), 1);
},
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
});
Here is where the array is accessed from within the application:
<ion-view view-title="Chats">
<ion-content>
<ion-list>
<ion-item class="item-remove-animate item-avatar item-icon-right" ng-repeat="chat in chats" type="item-text-wrap" href="#/tab/chats/{{chat.id}}">
<div class="list card">
<div class="item item-avatar">
<img src="{{chat.face}}">
<h2>{{chat.name}}</h2>
<p>{{chat.lastText}}</p>
</div>
<div class="">
<img ng-src="{{chat.face}}">
</div>
<a class="item item-icon-left assertive" href="#/tab/chats/{{chat.id}}">
<i class="icon ion-cash"></i>
Get Deal!
</a>
</div>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
and below is the PHP file used:
<?php
define('HOST','host');
define('USER','user');
define('PASS','password');
define('DB','db');
$con = mysqli_connect(HOST,USER,PASS,DB);
$sth = mysqli_query($con, "SELECT * FROM chats;");
$rows = array();
while($r = mysqli_fetch_assoc($sth)) {
$rows[] = $r;
}
echo json_encode($rows);
mysqli_close($con);
?>
This is the controller.js:
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope) {})
.controller('ChatsCtrl', function($scope, Chats) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//
//$scope.$on('$ionicView.enter', function(e) {
//});
$scope.chats = Chats.all();
$scope.remove = function(chat) {
Chats.remove(chat);
};
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
.controller('AccountCtrl', function($scope) {
$scope.settings = {
enableFriends: true
};
});
I've tried using an async call (which i'm not totally familiar with). I need the array to be ready at the start of the app
Thanks!
This works :
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.factory('chats', function($http){
var chats = [];
var _loading = $http.get('http://swapi.co/api/people').then(function(res){
console.log(res.data.results);
chats = res.data.results;
});
return {
loading: _loading,
all: function(){
return chats;
}
};
});
myApp.controller('ChatsCtrl', function($scope, chats){
$scope.chats = [];
chats.loading.then(function(){
$scope.chats = chats.all();
});
});
</script>
</head>
<body ng-app="myApp">
<div ng-controller="ChatsCtrl">
<ul>
<li ng-repeat="chat in chats">{{chat.name}}</li>
</ul>
</div>
</body>
</html>
Since the Ionic framework is built on Angular, you can use the $http service. You need to request that PHP file from the $http service and then you will be able to read it as JSON. Try something like this for starters:
Make a service that has your API set up already, then call it in your controller file.
angular.module('starter.services', [])
.factory('MYAPI', function() {
return {
getChats: function() {
return $http.get('http://localhost/YOURFILEHERE.php');
}
}
});
Now, in your controller file, assuming you've injected the MYAPI service, you can call
MYAPI.getChats().then(function(response) {
$scope.chats = response.data;
}, function(error) {
console.error(error);
});
You will need to change the $http.get() path to reflect the path of the PHP file on your system.

AngularJS Custom Filter getting invoked multiple times with one change

Following are my questions on the code described below -
On page load, my below custom sort filter is getting called multiple times. why?
On selecting a select option (from directive), I want to trigger filter based on selected value (using two way binding). Here again filter is being called thrice. Why?
Can some one point me to answers? I know that Angular does a Dirty Check by comparing old and new digest, but why multiple and 3rd invocation (as mentioned in the above questions).
I have below directive -
angular.module("customDirectives", [])
.directive("sortAll", function () {
return {
restrict: "E",
scope: {
columns: "=sortcolumns",
optionselected: "=selectedoption"
},
templateUrl: '../Views/Directives/SortAll.html',
controller: function ($scope) {
$scope.sortOptions = [];
var asc = 'Ascending';
var desc = 'Descending';
$scope.getSortOptions = function () {
angular.forEach($scope.columns, function (item) {
$scope.sortOptions.push({ name: item + '-' + asc, value: asc });
$scope.sortOptions.push({ name: item + '-' + desc, value: desc });
});
$scope.optionselected = $scope.sortOptions[1];
return $scope.sortOptions;
}
}
};
});
Directive HTML -
<select name="sortOptions" id="sortOptions" class="form-control width-20percent pull-right"
ng-options="option.name for option in sortOptions"
ng-init="getSortOptions()"
ng-model="optionselected"></select>
And below Filter -
angular.module("customFilters", [])
.filter("sort", function ($filter) {
return function (data, sortOption) {
console.log(sortOption);
if (angular.isArray(data) && angular.isObject(sortOption)) {
var options = sortOption["name"].split('-');
var xc = options[1] == 'Ascending' ? false : true;
return $filter("orderBy")(data, options[0], xc);
} else {
return [];
}
}
});
Now my Controller code -
angular.module("productStore")
.controller("ProductListCtrl", function ($scope, $filter) {
});
And the main controller which gives the data -
angular.module("productStore")
.constant("dataUrl", "http://localhost:57398/testdata/Products.json")
.constant("productColumns", ["name","price","description"])
.controller("MainCtrl", function ($scope, $http, dataUrl, productColumns) {
$scope.data = {};
$scope.productColumns = productColumns;
$http.get(dataUrl)
.success(function (products) {
$scope.data.products = products;
})
.error(function (error) {
$scope.data.error = error;
})
});
HTML -
<body ng-controller="MainCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">PRODUCT STORE</a>
</div>
<div class="panel-default" ng-controller="ProductListCtrl" ng-hide="data.error" ng-cloak>
<div class="col-xs-8">
<sort-All sortcolumns="productColumns" selectedoption="selectedSortOption"></sort-All>
<div class="well padding-top-0px" ng-repeat="product in data.products | sort:selectedSortOption">
<h3>
<strong>{{product.name}}</strong>
<span class="pull-right label label-primary">
{{product.price | currency}}
</span>
</h3>
<span class="lead">{{product.description}}</span>
</div>
</div>
</div>
</body>
Sample Data -
[{
"category": "Watersports",
"description": "A boat for one person",
"name": "Kayak",
"price": 275,
"id": "05af70919155f8fc"
}]
On Page load -
On changing item in select -

pass data via on-click angularjs

I have a .json file with a list of cows with details about where each one lives.
I have two panels.
One panel displays the list of cows and I have this displayed using ng-repeat.
The second panel appears when the title of the cow is clicked on, which is all great and working. However I can't seam to work out how to pass the location of that particular cow. Is it possible to pass grab and pass the number in the cow array? I've tried passing {{'cow'}} thinking that this would represent the array id but I don't think I'm on the right track so thought I'd post up here.
Is there any way to pass the data so that only the location of the cow clicked shows up? Do I need to call a promise or something?
Thanks - code below of where I am so far
HTML
<html ng-app="animalApp">
<section ng-controller="AnimalController as animalCtrl">
<ul ng-controller="PanelController as panel">
<li ng-class="{ active: panel.isSelected(1)}" ng-show="panel.isSelected(1)">
<ul>
<li ng-repeat="cow in animalCtrl.cows">
<h2>
</h2>
</li>
</ul>
</li>
<li ng-class="{ active: panel.isSelected(2)}" ng-show="panel.isSelected(2)">
<p>This {{animalCtrl.cow.name}} lives in {{animalCtrl.cow.country}}</p>
Back to all cows
</li>
</ul>
</section>
</html>
JS
var app = angular.module('animalApp', [ ]);
app.controller('AnimalController', ['$http', '$scope',function($http, $scope){
var type = this;
type.cows = [ ];
$http.get('animals.json').success(function(data){
type.cows = data;
});
app.controller("PanelController", function() {
this.tab = 1;
this.selectTab = function(setTab) {
this.tab = setTab;
};
this.isSelected = function(checkTab) {
return this.tab === checkTab;
}
});
JSON
[
{
"name": "Angus",
"country": "UK"
},
{
"name": "Hereford",
"country": "Canada"
},
{
"name": "Dwarf Lulu",
"country": "Nepal"
},
{
"name": "Ongole",
"country": "India"
}
]
Here is a PLUNKER with the additions from the submitted answers(thanks) but yet to still get it to work. When clicking on 'Angus UK. I'm aiming to have the paragraph say 'This Angus lives in UK' - which is currently does not. Thanks again for the help.
You can just pass in cow. Based on your code, this seems to be what you want.
<li ng-repeat="cow in animalCtrl.cows">
<h2>
</h2>
</li>
controller
app.controller('AnimalController', ['$http', '$scope',function($http, $scope){
var type = this;
type.cows = [ ];
$http.get('animals.json').success(function(data){
type.cows = data;
});
type.cowId = function(cow){
this.cow = cow;
};
}
or if you wanted to pass in the index of the iterated cow
<li ng-repeat="cow in animalCtrl.cows">
<h2>
</h2>
</li>
controller
app.controller('AnimalController', ['$http', '$scope',function($http, $scope){
var type = this;
type.cows = [ ];
$http.get('animals.json').success(function(data){
type.cows = data;
});
type.cowId = function(id){
this.cow = type.cows[id];
};
}
Plunkr

angularjs i am using multiple select tag how to clear its all option after saved in db

How to clear multiple select option after saving into DB, i am using ng-model to clear it. Its clearing in back-end but not in UI side.
In controller I am writing:
smsType = {};
smsType.smsTypeId = [];
HTML code:
<div class="form-group">
<select ng-model="smsType.smsTypeId" ui-jq="chosen" multiple
class="w-md"
ng-options="s.id as s.name for s in smsoption.name">
</select>
</div>
Its not reflecting in ui side
Please give me some suggestion i am new to angularjs
Please see demo below
you missed $scope here
smsType.smsTypeId = [];
should be
$scope.smsType.smsTypeId = [];
// Code goes here
angular.module("myApp", []);
angular.module("myApp").controller("SelectCtrl", ["$scope",
function($scope) {
$scope.smsoption = {
name: [{
"id": "122",
"name": "denmark"
}, {
"id": "123",
"name": "france"
}, {
"id": "124",
"name": "italy"
}]
};
$scope.saveit = function() {
console.log($scope.selectCenter);
$scope.smsType.smsTypeId = [];
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h1>ngOption demo</h1>
<div ng-app="myApp">
<div ng-controller="SelectCtrl">
<select ng-model="smsType.smsTypeId" ui-jq="chosen" multiple class="w-md" ng-options="s.id as s.name for s in smsoption.name">
</select>
<hr/>You have chosen:
<span ng-repeat="type in smsType.smsTypeId">{{type}} | </span>
<button ng-click="saveit()">Save</button>
</div>
</div>
The model is the output, not the input. To clear it you need to clear smsoption. The model should reflect the options you have selected, not the other way around.
smsoption = [];
Should do it

Categories