When a user clicks through to their User Profile Page they are supposed to see friendly dates. Instead they see the raw Javascript date. I am using a service to transform the data. I think the problem is related to ng-click and href that is being used. I do this throughout my Single Page Appllication using the MEAN Stack and the only pages that have problems are the ones that use ng-click to open.
The link which navigates the user to their User Profile is the following
<a ng-show="authenticated" href="#/usrProfile" ng-click="showUser(current_user)">{{current_user}} </a>
Clicking on the above html link opens their User Profile page. The correct date time is there but it is not rendered properly. It shows, for example "2015-12-01T01:19:22.947Z", instead of "Nov 30, 2015" which is adjusted for their timezone and more human readable. If the user clicks the back button of the browser, then clicks the forward button it will show the same date properly rendered.
The date is rendered by Angular outside the controller using a service. The service renders the date with the following code
vUsrProfile.usrCreatedDate = $filter('date')(vOriginalUsrCreatedDate,"MMM d, y", $rootScope.current_offset);
The data in the service is passed to the controller using the following code
var usrSingle = usrTracker.getProperty();
$scope.usrSingle = usrSingle;
The code to display that date is this code
<h5 title="Date {{usrSingle.username}} joined">{{usrSingle.usrCreatedDate}}</h5>
I am missing something. It feels like the data is being displayed before the service has transformed it.
I hope this makes sense. It seems like a hard problem to describe.
MORE DETAILS:
Controller code. Passing data from one controller to another.
// Controller for link
app.controller('mainController', function ($scope, usrTracker, usrServiceById) {
// removed non-relevant code ...
// get single user data
$scope.showUser = function (vUsername) {
usrTracker.setProperty(usrServiceById.get({ "username": vUsername }));
};
// removed non-relevant code ...
});
// Controller User Profile Page
app.controller('usrPageController', function ($scope, usrTracker) {
var usrSingle = usrTracker.getProperty();
$scope.usrSingle = usrSingle;
// removed non-relevant code ...
});
// factory for a single user
app.factory('usrServiceById', function ($resource) {
return $resource('/api/usrProfile/:id', { id: '#_id' });
});
// factory to hold user data between controllers
app.factory('usrTracker', function ($filter,$q,$rootScope) {
var vUsrProfile = {
username: 'username',
usrEmail: 'usrEmail'
, usrFirst: 'usrFirst'
, usrLast: 'usrLast'
, usrTimezone: 'usrTimezone'
, usrGender: 'usrGender'
, usrBirth: 'usrGender'
, usrPrefHours: 'usrPrefHours'
, usrSocAuth: 'usrSocAuth'
, usrCreatedDate: 'usrCreatedDate'
, usrAccessToken: 'usrAccessToken'
, usrRefreshToken: 'refreshToken'
, usrOffset: '+0000'
, usrDesc: 'usrDesc'
, userSocId: 'userSocId'
};
return {
getProperty: function () {
var vOriginalUsrCreatedDate = vUsrProfile.usrCreatedDate;
vUsrProfile.usrCreatedDate = $filter('date')(vOriginalUsrCreatedDate,"MMM d, y", $rootScope.current_offset);
return vUsrProfile;
},
setProperty: function (value) {
vUsrProfile = value;
}
};
});
Related
i'm doing a crud like a phone list,
in a view i want to add persons to my list, and in another view i want to show that peoples,
for do that, i'm using two controllers, and a service to store my array with the persons.
to add peoples i'm using set way to pushing it to array when i click on a button and thats works fine(possible to see with console.log at salvar function in service).
My problem is, when i go to show the list with the get method after added some persons with set, the get method still returning my list like she starts (empty). how i can fix this?
angular
.module('moduloLista')
.factory('addMostrarService', addMostrarService);
function addMostrarService() {
var listacontatos = [
];
var salvar = function(obj){
listacontatos.push(obj);
};
var getLista = function(){
return listacontatos;
};
return{
salvar: function(obj){
salvar(obj);
},
getLista: function(){
return getLista();
}
}
}
^ Service Code
angular
.module('moduloLista')
.controller('testeController',testeController);
testeController.$inject = ['addMostrarService'];
function testeController(addMostrarService) {
var vm = this;
vm.dadoslista = addMostrarService.getLista();
console.log('vm.dadoslista');
}
^ controller to get the list from service.
I'm making something that works similarly to this plunker that I created.
In my app I'm using Firebase/AngularFire.
In the plunker you can see that when you check-in to a meeting, the icon changes to a success icon. In my app this is where I store that info in Firebase like this:
$scope.join = function(hash) {
console.log(hash);
var ref = dbRef.ref('meetings/'+hash+'/users')
var meetingInfo = $firebaseArray(ref);
meetingInfo.$add({
date: firebase.database.ServerValue.TIMESTAMP,
user_name: $scope.name,
user: $scope.currentUser
}).then(function(ref) {
var key = ref.key;
var index = meetingInfo.$indexFor(key);
console.log(key, index);
$uibModalInstance.close();
});
};
So the data gets added into Firebase and then the modal closes.
I also have a similar controller and view for listing out the meetings just like in the plunker.
In the plunker I send a variable through $rootScope so it's accessible in the listingController. That works, but as you can see I can only check-in to one meeting, and after I refresh or check-in to another meeting, the check-mark disappears.
I would like to know how to persist this change so that anytime I check-in to a meeting the check-mark will stay. I'm thinking that I need to edit something in my listing controller so that when it grabs the data, it can check to see if someone has checked in to the meeting, and display the checkmark, so here is my Firebase list controller:
app.controller('listController', ['$scope', '$rootScope', '$firebaseArray', '$firebaseObject', '$uibModal', function($scope, $rootScope, $firebaseArray, $firebaseObject, $uibModal) {
var ref = firebase.database().ref('meetings');
var list = $firebaseObject(ref);
list.$loaded().then(function(data) {
$scope.lobbies = list;
});
}]);
EDIT
The way Firebase stores the data is like this:
---meetings
------random hash (key)
---------date
---------name
---------attendees
------------random hash
---------------date
---------------name
When I do my ng-repeat it's like this: ng-repeat="(key, meeting) in meetings" so I can access the meeting data like meeting.name. How should I go about accessing the attendees to check if the current user is in the meeting?
SOLUTION
This question helped me out a lot in addition to the HTML snippet that idan provided
You need to decide where you keep this data and how.
You can, for example, hold a list of attendees in the meeting. Something like:
{
users: {
userid1: {
name: 'Someone'
},
userid2: {
name: 'Someone else'
}
// ...
},
meetings: {
meetingid1: {
location: 'Somewhere',
title: 'Gala',
attendees: {
userid1: true,
userid3: true
// ...
}
}
// ...
}
}
Then you can check if a user attends a meeting to change the button.
Also the ng-if there to change buttons seems too much. You can use ng-class on the button and icon, then you'll have only one button instead of two.
<button class="btn btn-sm" ng-click="open(meeting)" ng-class="user.$id in meeting.attendees ? 'btn-success' : 'btn-primary'">
<i class="fa" ng-class="user.$id in meeting.attendees ? 'fa-check' : 'fa-sign-in'"></i>
</button>
One more thing: strongly recommend to read Angular style guide 1 and Angular style guide 2. Both contain great tips to help you maintain your app easily.
It's two page user registeration process depending on the role the second page could be different but the first page will always remain the same. what I want I that user can go forward and backwards on both screens with persistent data. I trying a static page at start and then hide it and add the second template from route.
This is my angular app controller.
app.controller('addlandlordController' , function($scope , $http , $route ,API_URL , $routeParams , uploadService ){
$scope.API_URL = API_URL;
$scope.landVisible = true;
$scope.IsVisible = true;
if( $routeParams.test)
{
scope.$apply(function () {
$scope.IsVisible = false;
});
alert( $routeParams.test);
}
$scope.adduser = function($route){
var data = $.param({
fName: $scope.firstName,
lName: $scope.lastName,
role: 'landlord',
email: $scope.email,
linkId: $scope.linkId,
password: $scope.password,
});
var config = {
headers : {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
}
$http.post(API_URL + 'user' , data , config)
.then(
function(response){
//$scope.IsVisible = false;
//alert('success');
},
function(response){
// failure callback
alert('fail');
}
);
}
});
I have a div in html like this,.
<div id="content" class="container1" ng-controller='addlandlordController' >
<div ng-show = "IsVisible">
And following is my route in config,.
app.config(function($routeProvider){
$routeProvider.when('/landlord' , {
templateUrl : 'template/addlandlord.html',
controller : 'addlandlordController',
resolve: {
test: function ($route) { $route.current.params.test = true; }
}
})
});
What I want is that when the user click on the following button.
Create an Account</button>
On click that button #/landlord will be added to the url and the route config code will run and add the other template in ng-view which is happening. Now next step is to hide the old div above in such a way that when user go back one sten only the previous code should show and when user goes again into the next screen only the next template should be visible and mean while data should remain same for the both views.
Issues I am facing is
Css is for template view is missing although the css files are already in the commen header. But appears when a place css in the style within template.
if I hide the first div in the response of adduser then if user go back it still hidden. it doesn't appears unless I refresh the page.
But if went to hide it through route config the value turn false but div never hides.
Please check this
scope.$apply(function () {
$scope.IsVisible = false;
});
You are using $apply on scope, but not in $scope.
And $applyAsync is preferable method to trigger digest without risking of error "$digest already in progress"
$applyAsync example:
$element.on('click', ()=>{
$scope.model.testValue = 'I have been updated not from angular circle';
$scope.$applyAsync();
});
Link to the docs
Nice article to read
I use in service in my angular app as follows:
app.service('sharedProperties', function () {
var property;
return {
getProperty: function () {
return property;
},
setProperty: function(value) {
property = value;
}
};
});
$scope.Somefunc= function(Mname)
{
$http.post("SomeServlet",{
"name": Mname,
}).then(function(response) {
sharedProperties.setProperty(response.data);
window.location = "/blabla/page2.html";
});
};
And in page2 (another conroller) i get the value:
app.controller('controller2', function($scope,$http,sharedProperties) {
$scope.UserProperties = sharedProperties.getProperty();
});
and its doesnt work, always i get undefined.
In order for it to work, you must set the angular routing function which will take care of moving to another page without refreshing your current page (also called SPA - Single Page Application).
Take a look here, at the example in the end of the page there are the different pages and files in the mini system.
I remind you that angular is meant to work with single page applications, so if you refresh the page and change it into another one - You sort of lose the point of using it.
Im AngularJs newbie:).
But I have 3 components: controller C1 (for entering search input and clicking submit button),controller C2 (for div which will receive results from SearchService and display it) and service searchService for sending some hardocoded results.
THe idea is that after submitting search text, I have to submit it twice. With one submit click, view of ui-router is updated to partial page without results loaded. After second click the results are displayed.
Then next searches are done on search view page, all is ok, one click gives needed data.
How to fix it: I want to change ui-router view and get results from service with one click?
C1 method code (started after submiting searchText)
$scope.searchText = function searchText(text) {
$log.log("Method searchText with text: " + text);
//var parametersObject = {searchText: text, results: assetResults}
$state.go('search');
$log.log("SearchInputBoxController: rootScope Broadcasting message: " + text);
$rootScope.$broadcast('DoSearch', text);
$log.log("SearchInputBoxController finished");
};
C2 method: event handler for event 'DoSearch'
$scope.$on('DoSearch', function (event, data) {
$scope.asset = searchService.search(data);
$scope.searchText = data;
});
searchService code:
Application.Services.factory('SearchService', ['SearchServiceResource', '$q',
function (SearchServiceResource, $q) {
return {
search : function (searchText)
{
var result = [
{id: 'aaaaa', sn:"1234-1234-1234-1235", name:"DCU_name1", type: "DCU", tags: ["tag1", "tag2"]},
{id: 'aaaaa', sn:"1234-1234-1234-1235", name:"DCU_name2", type: "DCU", tags: ["tag1", "tag2"]},
{id: 'aaaaa', sn:"1234-1234-1234-1235", name:"NODE_name1", type: "DCU_Node", tags: ["tag1", "tag2"]}
];
return result;
}
};
}]);
I believe the clicking twice is because the first click is triggering the state change, then the broadcast occurs, and then the state change occurs. The second click, the state doesn't need to change, and the current now unchanged controller gets the broadcast. There are a couple different approaches I can think of (and I would def shy away from rootscope broadcasting):
in your shared service, maintain a search string variable and on your
controller, put watch on that service's variable.
change your route/state settings to include a parameter like /search/:searchTerm and in the controller, look for the state established searchTerm variable and on the controller load see if searchTerm is provided and fire the search. Some more info here
Let me now if you need any help or more specifics on the ideas listed.