AngularJS Not Getting Latest Data From Database - angularjs

I have a factory.all() function that gets called on page load. However, whenever I enter a new entry into my MongoDB or delete one, it is not refreshing. I am logging (data) to console to see how many objects are returned. Currently, I have four being returned. Even when I delete one of them, and refresh the page, 4 objects are still logged to the console. Is this a Browser caching issue? Is there a way to counter this?
My controller:
angular.module('quizCtrl', [])
.controller('quizController', function(Quiz) {
// Assign local variable to be used in application
var vm = this;
// To Load All Quizzes on Application
Quiz.all().success(function(data) {
console.log(data);
});
My Factory:
angular.module('quizService', [])
.factory('Quiz', function($http) {
// create a new object
var quizFactory = {};
// get a single quiz
quizFactory.get = function(id) {
return $http.get('/api/quiz/' + id);
};
// get all quizzes
quizFactory.all = function() {
return $http.get('/api/quiz/');
};
// create a quiz
quizFactory.create = function(quizData) {
return $http.post('/api/quiz/', quizData);
};
// update a quiz
quizFactory.update = function(id, quizData) {
return $http.put('/api/quiz/' + id, quizData);
};
// delete a quiz
quizFactory.delete = function(id) {
return $http.delete('/api/quiz/' + id);
};
// return our entire quizFactory object
return quizFactory;
});
Endpoint:
// GET request to load ALL quiz at once
apiRouter.route('/quiz')
.get(function(req, res) {
Quiz.find({}, function(err, quiz) {
if (err) res.json({ message: "Error: " + err})
res.json(quiz);
});
});
// GET request to get a specific quiz only
apiRouter.route('/quiz/:quiz_id')
// get the user with that id
.get(function(req, res) {
Quiz.findById(req.params.quiz_id, function(err, quiz) {
if (err) res.json("Error: " + err);
// return that user
res.json(quiz);
});
});
HTML Displaying Data
<div class="panel panel-success" ng-show="quiz.quiz">
<div class="panel-heading">
<div class="panel-title">{{ quiz.quiz.question }}
<div style="float:right">
{{ ex.createdAt | date : "MMM d, y h:mm a" }}
</div>
</div>
</div>
<div class="panel-body">
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[0], quiz.quiz._id, quiz.quiz.correctAnswer)" ng-disabled="quiz.isDisabled">A. {{ quiz.quiz.answers[0] }}</button><br><br>
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[1], quiz.quiz._id, quiz.quiz.correctAnswer)"" ng-disabled="quiz.isDisabled">B. {{ quiz.quiz.answers[1] }}</button><br><br>
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[2], quiz.quiz._id, quiz.quiz.correctAnswer)" ng-disabled="quiz.isDisabled">C. {{ quiz.quiz.answers[2] }}</button><br><br>
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[3], quiz.quiz._id, quiz.quiz.correctAnswer)"" ng-disabled="quiz.isDisabled">D. {{ quiz.quiz.answers[3] }}</button><br><br>
<div class="alert alert-info" role="alert" ng-if="(quiz.successMessage)">
<strong>{{ quiz.successMessage }}</strong> is correct.
</div>
<div class="alert alert-danger" role="alert" ng-if="(quiz.failureMessage)">
<strong>{{ quiz.failureMessage }}</strong> is incorrect.
</div>
<div class="alert alert-success" role="alert" ng-if="(quiz.correctMessage)">
Correct answer is: <strong>{{ quiz.correctMessage }}</strong>
</div>
Correct So Far: {{ quiz.correctSoFar }}
</div>
<div class="panel-body">
<div class="panel-body">Posted by: {{ exam.postedBy }}</div>
<div style="float:right">
<button class="btn btn-success" type="button" ng-click="quiz.nextQuestion()" ng-if="quiz.isDisabled">Next</button>
</div>
</div>
</div>
</div>

Related

two way binding not working even with dot notation

I'm starting with AngularJS and I am using a controller variable to navigate an array of questions, and it is working when using nextQuestion function, index gets updated and the next question is shown in the view, but if I try to obtain the same value (index) in a different function, it always returns 0.
I have seen on other questions that you should use an object to contain the variable to not manipulate primitive types directly in the controller, but it still does not work.
My controller:
myApp.controller('SurveyController',['$scope','$http', '$location','$routeParams','surveyMetrics','DataService',function($scope,$http, $location,$routeParams,surveyMetrics,DataService){
console.log('LOADED QUIZ CONTROLLER');
var vm = this;
vm.scope = {
index: 0
};
vm.surveyMetrics = surveyMetrics;
vm.surveyQuestions = DataService.surveyQuestions;
vm.DataService = DataService;
/*
vm.getQuestions = function(){
$http.get('/api/questions').then(function(response){
$scope.questions = response.data;
});
}
*/
/*
vm.activateSurvey = function(){
surveyMetrics.changeState(true);
}
*/
vm.getCurrentIndex = function(){
return vm.scope.index;
}
vm.nextQuestion = function () {
console.log('NEXT QUESTION!');
console.log('NUMBER OF QUESTIONS: '+ vm.surveyQuestions.length);
var currentIndex = vm.getCurrentIndex();
var newIndex = currentIndex+1;
scope = {};
if (currentIndex == vm.surveyQuestions.length) {
newIndex = vm.surveyQuestions.length -1;
}
vm.scope.index = newIndex;
console.log('Inside Object: '+vm.scope)
console.log('vm.index'+vm.scope.index);
console.log('vm.indexFunction'+vm.getCurrentIndex());
}
/*
vm.previousQuestion = function () {
console.log('PREVIOUS QUESTION!');
console.log('NUMBER OF QUESTIONS: '+ vm.surveyQuestions.length);
if (vm.scope.index == 0) {
vm.scope.index = 0;
}else{
vm.scope.index--;
}
}
*/
vm.activeSurveyQuestion = function(questionId,index){
console.log('question id and index',questionId,index);
if (questionId == index) {
var navBtn = document.getElementById('navBtn_'+index);
navBtn.classList.add('active');
}
}
vm.navigateSurvey = function () {
var answerPane = document.getElementById('answer-pane');
document.onkeydown = function (e) {
console.log('INSIDE KEYDOWN: ')
e.preventDefault();
var pressedKey = e.keyCode;
console.log('PRESSED KEY IN SURVEY: ' + pressedKey);
if (pressedKey === rightArrow) {
console.log('survey - right arrow pressed');
document.getElementById('nextQuestionBtn').click();
console.log('FUCKING INDEX FML!: '+vm.getCurrentIndex()+' | '+vm.scope.index);
var questionType = DataService.getQuestionType(vm.scope.index);
console.log('Survey Controller: question type: '+questionType);
}
if (pressedKey === leftArrow) {
console.log('survey - left arrow pressed');
document.getElementById('previousQuestionBtn').click();
}
(...)
My View:
<!--Satisfaction Survey-->
<div ng-controller="SurveyController as survey" ng-init="survey.getSurvey();">
<!--
<p ng-repeat="question in survey.surveyQuestions" ng-show ="survey.surveyMetrics.surveyActive">
{{question.question}}
</p>
-->
<!--Survey Modal -->
<div class="modal fade" id="surveyModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="text-center"> Customer Satisfaction Survey</div>
<div class="modal-header">
<h4 class="modal-title">{{survey.surveyQuestions[survey.getCurrentIndex()].question}}</h4>
</div>
<div class="modal-body survey" id="answer-pane">
<div class="row">
<div class="col-sm-2 survey-left-arrow" ng-click="survey.previousQuestion();" id="previousQuestionBtn">
<p>‹</p>
</div>
<div class="col-sm-8">
<!-- <p ng-repeat="answer in survey.surveyQuestions[survey.index].answers">{{answer}}</p> -->
<p ng-repeat="answer in survey.surveyQuestions[survey.getCurrentIndex()].answers">
<button type="button" class="btn" id="answerId_{{survey.getCurrentIndex()}}"
ng-class="{'survey-check-box': (survey.surveyQuestions[survey.getCurrentIndex()].type !== 'SingleChoice'),
'survey-btn_{{($index+1)}}': (survey.surveyQuestions[survey.getCurrentIndex()].type === 'SingleChoice')}">
<input type="checkbox" ng-if="survey.surveyQuestions[survey.getCurrentIndex()].type !== 'SingleChoice'"> {{answer}}
</button>
</p>
</div>
<div class="col-sm-2 survey-right-arrow " ng-click="survey.nextQuestion();" id="nextQuestionBtn">
<p>›</p>
</div>
</div>
</div>
<div class="text-center">
<strong> <p>Question: {{survey.surveyQuestions[survey.scope.index].questionNum}} of {{survey.surveyQuestions.length}}</p> </strong>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
<!-- <nav aria-label="Survey navigation">
<ul class="pagination pagination-sm justify-content-center">
<div ng-repeat="question in survey.surveyQuestions" >
<li class="page-item">
<a class="page-link" id = "navBtn_$index" ng-click="survey.index = $index">{{question.id}}</a>
</li>
</div>
</ul>
</nav> -->
</div>
</div>
I would like for the controller to change the variable and the view to update accordingly
Thank you for your time and thank you in advance.
It's 'survey.scope.index' not 'survey.index' in your HTML. I think you may be unclear the difference between using 'this' and '$scope'. You're mixing the two together which is not necessary. I would suggest removing 'scope' and just reference it in your HTML as 'survey.index'.

how to refresh the list in AngularJs?

I have to implement the share product functionality with the user after share i have to refresh the list here selectedSharedIntermediaryInAlbum is our array so how to implement this?
//refreshSharedIntermediary for refresh the lsit
$scope.refreshSharedIntermediary = function() {
$scope.selectedSharedIntermediaryInAlbum = $scope.selectedSharedIntermediaryInAlbum;
}
<div class="w3-right">
<button class="btn btn-rose btn-sm" tltle="refresh data" ng-click="refreshSharedIntermediary()">
<i class="glyphicon glyphicon-repeat"></i>
</button>
</div>
You can use $scope.reload function where need to reload the list ... i have used below concept :
<div class="well well-lg" ng-repeat="item in list track by item.id">
<button class="btn btn-default"
ng-click="collapsedFlags[item.id] = !collapsedFlags[item.id]">
{{ item.isCollapsed ? '+' : '-' }}
</button>
<div uib-collapse="collapsedFlags[item.id]" ng-bind="item.value"></div>
</div>
$scope.reload = function () {
$http.get('list.json').then(function (data) {
$scope.list = data && data.data || [];
});
};
$scope.collapsedFlags = {};
$scope.reload();
Working example : https://plnkr.co/edit/87vVb8Jjyz6yFGAjiHBK?p=preview

How to popup chat window using node.js

I am working on node.js and began to create a chat application I have built it successfully but the problem is that I want the chat window should be open when the client click on the name of the sender(who sent the message to the client).
I will show you the example what I have done till now.
Here you can see that the chat box is already open but I want it should open when a user is selected from "List of users" and the content of chat box should be replaced whenever a new user is selected and previous content should be removed.
Here is my index.html code :
<div class="col-md-4 user-list">
<h2>List of Users</h2>
<ul class="list-group">
<li class="list-group-item"
ng-repeat="user in userList"
ng-class="{ 'active' : user.id == selectedUser.uid}"
ng-click = seletedUser(user.id,user.userName);
ng-style="{
'cursor': user.id === socketId ? 'not-allowed' :'pointer'
}"
>
<span id='{{user.id}}' >{{ user.id === socketId ? 'You': user.userName }}</span>
<span id='{{user.id + "notify"}}' style="color:black; opacity:0.5; font:2px; padding:5px; visibility:hidden;"> {{'typing...'}}</span>
</li>
</ul>
</div>
</div>
<div class="container" id="messages">
<div class="row">
<div class="col-md-8">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span> {{'Chat -' + selectedUser.uname}}
</div>
<div class="panel-body">
<ul class="chat col-md-7"
ng-repeat = "message in messages"
ng-style ="{'float':message.fromid == socketId ? 'left' : 'right'}">
<li>
<div class="clearfix">
<div class="direct-chat-text"
ng-style = "{'background-color': message.fromid == socketId ? '#d9edf7' : '#62f3bc'}"
>
{{message.msg}}
</div>
</div>
</li>
</ul>
<br></br>
</div>
<div class="panel-footer">
<div class="input-group">
<textarea elastic type="text" class="form-control custom-control" ng-model='message' ng-keyup="keyup()" ng-keydown="keydown()" ng-change="change()" placeholder="Type your message here..."></textarea>
<span class="input-group-addon btn btn-primary" ng-click="sendMsg()"><i class="glyphicon glyphicon-send"></i></span>
</div>
</div>
</div>
</div>
</div>
</div>
If you would require any other information related to code please comment.
As I am newbie to node.js so help me to solve my problem.
UPDATE
My script.js code which have sufficient details:
app.controller('app', ($scope,$timeout,socket) => {
$scope.socketId = null;
$scope.selectedUser ={ uid: null, uname: null};
$scope.messages = [];
$scope.msgData = null;
$scope.userList = [];
var TypeTimer;
var TypingInterval = 1000;
$scope.username = window.prompt('Enter Your Name');
if ($scope.username === '') {
window.location.reload();
}
$scope.seletedUser = (id,name) => {
if(id === $scope.socketId)
{
alert("Can't message to yourself.")
}
else
{
$scope.selectedUser =
{
uid: id,
uname: name
}
}
};
$scope.sendMsg = () => {
// const keyCode = $event.which || $event.keyCode;
if ($scope.message !== null && $scope.message !== '' && $scope.selectedUser.uid !== null) {
socket.emit('getMsg',{
toid : $scope.selectedUser.uid,
fromid: $scope.socketId,
msg : $scope.message,
name : $scope.username
});
$timeout.cancel(TypeTimer);
TypeTimer=$timeout( function(){
socket.emit('getTypingNotify',{
toid : $scope.selectedUser.uid,
fromid: $scope.socketId,
msg:"hidden"
});
});
$scope.message = null;
console.log($scope.selectedUser.uid);
}
else
{
alert("enter a message or select a User to send message");
}
};
socket.emit('username',$scope.username);
socket.on('userList', (userList,socketId) => {
if($scope.socketId === null){
$scope.socketId = socketId;
}
$scope.userList = userList;
});
socket.on('exit', (userList) => {
$scope.userList = userList;
});
socket.on('setMsg',(data) => {
document.getElementById(data.fromid+'notify').style.visibility= data.msg;
});
socket.on('sendMsg', (data) => {
//console.log('send');
$scope.messages.push(data);
});
my understanding is u want to show a pop up on click of a button or some text box u can use angular bootstarp model as shown here
"https://plnkr.co/edit/?p=preview"
and control the close and open in angularjs contoller and send the chat details too server side
After searching some tutorials and questions(on StackOverflow) I found a way and going to share with you all.
I created a directory name "open" and an attribute visible of this "open" directive to show and hide the dialog.
app.directive('open',function() {
return {
restrict: 'E',
template: `<div class="container">
<div class="row">
<div class="col-md-8">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span>{{"Chat -" + selectedUser.uname}}
</div>
<div class="panel-body">
<div ppp-chat></div>
<br></br>
</div>
<div class="panel-footer">
<div class="input-group">
<textarea msd-elastic type="text" class="form-control custom-control" ng-model="message" ng-keyup="keyup()" ng-keydown="keydown()" ng-change="change()" placeholder="Type your message here..."></textarea>
<span class="input-group-addon btn btn-primary" ng-click="sendMsg()"><i class="glyphicon glyphicon-send"></i></span>
</div>
</div>
</div>
</div>
</div>
</div>`,
replace:true,
scope:false,
link: function postLink(scope,element,attrs) {
scope.$watch(attrs.visible,function(value){
if(value == true)
{
$(element).show();
}
else
$(element).hide();
});
$(element).on('show.bs.open',function() {
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('hidden.bs.open',function() {
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
}
};
});
And a method in controller to toggle the chat window(hide or show)
$scope.toggleChat = () => {
$scope.showChat = false;
$scope.showChat = !$scope.showChat;
};
this toggleChat is used to change the value of showChat scope variable that is used to turn on(off) the visibility of chat box by alterating the showChat value as true or false.
In html I have replaced my id="messages" element( with its child and subchild) with
<open visible="showChat">
</open>

I can't get ng-repeat data to go on my page for visiting another user profile page

I'm am trying to fetch data by clicking on a user name to redirect the user on his profile page.
I am trying to do this with ng-click like this:
<p style="font-size:11px; color: grey; " ng-click="seeProfile(gterest);changelocation();"><b>{[{gterest.author}]}</b></p>
My two controller functions:
$scope.seeProfile = function (gterest) {
console.log(gterest);
var user = gterest.author;
$http.post('/userProfile/', {user: user}).then(function (results) {
console.log(results);
$scope.userProfileList = results.data;
})
};
$scope.changelocation = function () {
$window.location.href = '/userProfile/';
}
My server function:
router.post('/', function (req, res) {
var user = req.body.user;
console.log(user);
mongoose.model('Gterest').find({"author": user},function(err, gterests){
if(err) console.log(err);
console.log(gterests)
res.json(gterests);
});
})
And here I'm trying to display the data:
<div ng-controller="allGterest">
<div masonry>
<div class="masonry-brick pinterest" ng-repeat="user in userProfileList">
<img ng-src="{[{user.image}]}" alt="aaa" style="width: 238px;">
<p style="font-size:11px; color: grey; "><b>{[{user.author}]}</b></p>
<p style="margin-top: 5px;" ><b>{[{gterest.title}]}</b></p>
<button class="btn btn-danger btn-xs" style="margin-bottom: 2px;"><span class="glyphicon glyphicon-heart"></span></button>
</div>
</div>
</div>
This doesn't give me any erros but my screen is blank, I don't know what to do.
Please help! Thanks!
EDIT:
I'm am using {[{}]} insted of {{}} because I use handlebars a my view, so in my module file I have
app.config(function ($interpolateProvider) {
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});
It looks like that you should use {{your_varibale}} rather than {[{your_varibale}]} . Below is the updated code.
<div ng-controller="allGterest">
<div masonry>
<div class="masonry-brick pinterest" ng-repeat="user in userProfileList">
<img ng-src="{{user.image}}" alt="aaa" style="width: 238px;">
<p style="font-size:11px; color: grey; "><b>{{user.author}}</b></p>
<p style="margin-top: 5px;" ><b>{{gterest.title}}</b></p>
<button class="btn btn-danger btn-xs" style="margin-bottom: 2px;"><span class="glyphicon glyphicon-heart"></span></button>
</div>
</div>
</div>

View not refreshing after successful http.get from factory (chained promises in use)

I have read more tutorials and posts on this particular subject than I care to admit but I still haven't been able to locate a solution. I need the view to refresh after the chained promise returns which is bound to $scope.p.devices. I have tried disabling cached views (still disabled) and a number of other solutions. Hoping someone on here can point me in the proper direction.
HTML:
Device List
<md-card>
<ion-content>
<div class="card-content">
<div class="device-content-detail"
collection-repeat="device in p.devices"
collection-item-height="136px"
collection-item-width="100%">
<div class="card-content">
<h1 class="md-title">
<span>
<i class="fa fa-crosshairs" aria-hidden="true"></i>
Device List
</span>
</h1>
{{device.name}}
</div>
</div>
</ion-content>
</md-card>
<md-list>
<md-card ng-if="!isAnimated" class="card-item" ng-repeat="device in p.devices track by $index">
<md-card-content>
<div class="card-content">
<h1 class="md-title">
<span>
Device List
<i class="fa fa-crosshairs" aria-hidden="true"></i>{{device.name}}
</span>
</h1>
<div class="device-content-detail">
<i class="fa fa-wifi" aria-hidden="true"></i>{{device.connected}}
<i class="fa fa-heartbeat" aria-hidden="true"></i>{{device.last_heard}}
</div>
</div>
</md-card-content>
</md-card>
Controller:
appControllers.controller('devicesCtrl', function ($scope,$state,$stateParams,$timeout,$mdDialog,$ionicHistory,$ionicLoading,particle,pDevices,safeparse) {
//$scope.isAnimated is the variable that use for receive object data from state params.
//For enable/disable row animation.
var debug = true;
$ionicLoading.show({
content: 'Getting Devices',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
$timeout(function () {
pDevices.getpDevices().then(function(data) {
$scope.p.devices = data;
if (debug) console.log(debug + 'time out got particle.io device list: ', $scope.p.devices);
$scope.isLoading = false;
if (debug) console.log(debug + 'time out complete, hiding ionicLoading: ');
$ionicLoading.hide();
}, function() {
$scope.p.showAlertDialog($event);
$scope.error = 'unable to load devices'
});
}, 2000);
$scope.initialForm = function () {
//$scope.isLoading is the variable that use for check statue of process.
$scope.isLoading = true;
$scope.isAnimated = $stateParams.isAnimated;
};// End initialForm.
$scope.$watch('p.devices', function (newVal, oldVal){
console.log(newVal, oldVal)
});
$scope.p = {
currentDevice: '',
deviceId: particle.setDevice(),
token: particle.setToken(),
devices: [],
getDevices: function () {
pDevices.getpDevices().then(function(deviceList) {
if (debug) console.log(debug + 'getDevices got particle.io device list: ', deviceList);
$scope.p.devices = deviceList.data;
});
},
// Select the current device for particle platform
setDevice: function (deviceId) {
if (deviceId) {
if (debug) console.log(debug + 'setDevice', deviceId);
$scope.p.deviceId = deviceId;
particle.setDevice(deviceId);
$scope.startup();
}
return $scope.p.deviceId;
}
};
showAlertDialog = function ($event) {
$mdDialog.show({
controller: 'DialogController',
templateUrl: 'confirm-dialog.html',
targetEvent: $event,
locals: {
displayOption: {
title: "No Devices Found.",
content: "Unable to load Device List.",
ok: "Confirm"
}
}
}).then(function () {
$scope.dialogResult = "You choose Confirm!"
});
}// End showAlertDialog.
$scope.initialForm();
});// End of controller Device.
And finally the factory being called:
appServices.factory('pDevices', function($http, localstorage) {
root_url = 'https://api.particle.io/v1/'
var getpDevices = function() {
return $http.get(root_url + 'devices').then(function(response){
console.log('pDevices getpDevices: ', response.data);
return response.data;
});
};
return {
getpDevices: getpDevices
};
});
Screenshot of what I get:
Turns out the problem was entirely in my HTML/SASS div tags as well as my object array which was not device but Object. This is working but needing some formatting corrections.
<ion-view cache-view="false" title="Device List">
<!--note list section-->
<ion-content id="device-list-content" class="bg-white">
<md-list>
<md-card class="card-item"
collection-repeat="Object in p.devices"
collection-item-height="136px"
collection-item-width="100%">
<md-divider></md-divider>
<md-card-content>
<div class="card-content">
<h1 class="md-title-device">
<span>
<i class="fa fa-crosshairs" aria-hidden="true"></i> {{Object.name}}
</span>
</h1>
<div class="device-content-detail">
<div ng-show="Object.connected">
<i class="fa fa-wifi" aria-hidden="true"></i>
<i class="fa fa-heartbeat" aria-hidden="true"></i>{{Object.last_ip_address}}
</div>
<div ng-show="!Object.connected">
<i class="fa fa-wifi" aria-hidden="true"></i>
<i class="fa fa-heart-o" aria-hidden="true"></i>{{Object.last_heard}}
</div>
</div>
</div>
</md-card-content>
</md-card>
</md-list>
</ion-content>

Resources