Extract date from last item in JSON object (AngularJS) - javascript

I am dynamically creating an object on a web app using AngularJS. The idea is that the user can load new events as they click a button, for this to work I need to get the date of the last one so Ill know which ones to load next.
This is the code that generates the JSON object
services.getEvents().then(function(data){
$scope.events = data.data;
});
and my html...
<li ng-repeat="event in events | orderBy:'-event_date' ">
<span>{{event.event_date}},{{event.event_name}}, {{event.event_venue}}, {{event.event_description}} </span>
</li>
An example of one event...
{
"event_id":"1",
"event_name":"Event 1",
"event_date":"2014-09-26 00:00:00",
"event_venue":"Limerick",
"event_description":"stuff"
}
Is it possible to extract the latest date from a list of these so I can send it back to the API? Or am I going about this a wrong way altogether.
Im also using this an opportunity to learn AngularJS

var app = angular.module("app", []);
function MainCtrl ($filter) {
this.data = [
{
"event_id":"1",
"event_name":"Event 1",
"event_date":"2014-05-26 00:00:00",
"event_venue":"Limerick",
"event_description":"stuff"
},{
"event_id":"2",
"event_name":"Event 1",
"event_date":"2015-09-26 00:00:00",
"event_venue":"Limerick",
"event_description":"stuff"
},{
"event_id":"3",
"event_name":"Event 1",
"event_date":"2014-9-27 00:00:00",
"event_venue":"Limerick",
"event_description":"stuff"
}
];
this.lastOne =$filter('orderBy')(this.data,'-event_date')[this.data.length-1].event_date ;
}
angular.module("app").controller("MainCtrl", MainCtrl);
<html ng-app="app">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-controller="MainCtrl as vm">
<div class="container">
<h3>Latest One:{{vm.lastOne}}</h3>
</div>
</body>
</html>

To access the last element of an array use length -1
events[events.length - 1].event_date
if the response from the server is not sorted in any way you should filter first
var sortedArray = $filter('orderBy')($scope.events, '-event_date');
var lastDate = sortedArray[sortedArray.length - 1].event_date
hope this gets you on the way.

If you make your server side code return an array sorted by descending date, you could just take the date off the first item in your array. Something like:
events[0].event_date;
Failing that, you could do the sorting on the client side with something like:
events.sort(function(a, b){return new Date(a.event_date) < new Date(b.event_date);});
Then get the value of:
events[0].event_date;

Related

Can I make an attribute appear only once in a vue v-for

I have an array of people with associated teams. I want to display all the people in the record, but I only want to display their team name once.
Meaning, if the v-for loop has encountered this particular team name, it should put it in a new temporary array to signify that it should be unique, then when it encounters that team name again, checks it through that temporary array and prevent it from showing again.
Sample HTML Code:
<div id="a-list">
<div v-for="person in people">{{person.Name}}, {{person.Team}}</div>
</div>
Sample Vue Code:
var crew = new Vue({
el: "#a-list",
data: {
people:
[ { "Name": "Richard","Team":"DMS"}, { "Name": "Mark","Team":"VV"}, { "Name": "Steve","Team":"VV"}, {"Name":"Koji","Team":"MZ"}, {"Name":"Jamie","Team":"VV"} ]
}
});
Expected Output:
Richard, DMS
Mark, VV
Steve,
Koji, MZ
Jaimie,
Is this possible to do directly from the v-for loop and not in the JS file?
Edited to show more data that are not sequential
Update: As Fabio has pointed out, the above scenario wouldn't make much sense unless the order of the team is arranged sequentially in the output first. So his answer is correct.
This could be a solution:
<div id="a-list">
<div v-for="(person,index) in people"> {{person.Name}}, {{ ((index == 0) || person.Team != people[index-1].Team) ? person.Team : '' }}</div>
</div>

Angular ng-options selected object

why is this not working?
HTML:
<div ng-controller="MyCtrl">
<select class="rp-admin-rooms-selected-select" name="teacherSelect" id="teacher"
ng-model="teacherSel"
ng-options="teacher.name for teacher in teachers "
>
</select>
{{teacherSel}}
</div>
JS:
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.teachers = [
{name:'Facundo', id:1},
{name:'Jorge', id:3},
{name:'Humberto', id:5},
{name:'David', id:7},
]
$scope.teacherSel = {name:'Facundo', id:1};
}
I would expect to be the selected element be Facundo
The thing is, I know that its possible to do this via teacherSel = id
and ng-options="teacher.name as teacher.id"...
But I have the object yet their, and I need the new object. not just the id.
jsfiddle:
http://jsfiddle.net/Lngv0r9k/
Michael Rose got it right. Another option would be force angular to do the comparison by value using a track by statement, as follows:
ng-options="teacher.name for teacher in teachers track by teacher.ID"
This works in angular 1.2 and after.
Updated fiddle: http://jsfiddle.net/Lngv0r9k/3/.
The issue is that the comparison for the selected entry is done via reference, not value. Since your $scope.teacherSel is a different object than the one inside the array - it will never be the selected one.
Therefore you need to find the selected entry inside the array and then use this as follows: $scope.teacherSel = $scope.teachers[indexOfSelectedEntry].
See at the bottom of your updated jsfiddle: http://jsfiddle.net/Lngv0r9k/1/
On your example you dont give a teacher object to the room.teacher , so the ng-options cant match anything to the ng-model.
As you see on the screen below, value=? means that it cant find correct value to match up.
you could try for example:
$scope.room = {
teacher: $scope.teachers[an item index];
};
OR
$scope.room = {
teacher: {
"ID": "1",
"name": "Adolf Ingobert",
"short": "AD",
"display": "Adolf I.",
"sectionFK": "2",
"invisible": "0"
};
};

Reading JSON from html5 local storage

I have created some JSON data and stored them in the local storage of html5:
Key Value
storage1 {"pnumber": "0001", "branchid": "1"}
storage2 {"pnumber": "0002", "branchid": "2"}
storage3 {"pnumber": "0003", "branchid": "3"}
I would like to show those data in my html by using the ng-repeat function from angularjs. But I'm still not sure how to do it. Below is my failed method.
Controller function from the js file snippet.
.controller('TicketListCtrl', function($rootScope) {
for(var i=1;i<=3;i++)
{
var ticlist = JSON.parse(localStorage.getItem('storage' + i));
$rootScope.numbers = ticlist;
}
});
My html file snippet:
<div class="list">
<a class="item item-icon-left dark" href="#/app" ng-repeat="number in numbers">
<p>This is {{number.pnumber}}</p>
</a>
</div>
But it could not show the pnumbers. Do you guys know what's wrong?
numbers is an array so you need to push new values in it, instead of assigning it everytime.
$rootScope.numbers = [];
for(var i=1;i<=3;i++)
{
var ticlist = JSON.parse(localStorage.getItem('storage' + i));
$rootScope.numbers.push(ticlist);
}
Looks like numbers should be an array of objects, but is a single object instead.

creating a dynamic form that builds a multi dimensional array

I am a php developer that is new to angular and javascript in general but finding it really powerful and fast for creating interactive UIs
I want to create a form for a user to create an object called a program, a program has some basic info like title and description and it can have many weeks. I want their to be an 'add week' button that when pressed displays a group of form fields related to weeks, if pushed again it shows another group of form fields to fill in the second weeks information.
edit1: specifically, how I am adding the objects to scope.program with the addWeeks method.
secondly when I console.log the $scope.program it just looks very messy a lot of arrays within objects within objects. it just dosnt look like a clean array of data but maybe thats just because I am not used to javascript and or json? Each week is going to have up to 7 days obviously and each day can have numerous events so it just seems to me like it is going to be quite messy but maybe I should just have faith :p
finally how the addProgram method is creating the json object to be sent to the server
when the form is submitted it should post a json object that looks something like this
program {
title: 'name of programme',
desc: 'description of programme',
weeks: [
{
item1: 'foo',
item2: 'more foo'
},
{
item1: 'foo2',
item2: 'more foo 2'
}
]
]
}
here is a codepen of what I am doing right now but I am not sure it is the best or even an ok way to do it, particularly how I am appending the arrays/objects in teh addWeek method.
there are going to be many more layers to the form and the object it is posting(days, sessions, excersises etc) so I want to get the basics of doing this right before adding all of that.
html
<div ng-app="trainercompare">
<div ng-controller="programsController">
<input type="text" placeholder="Program Title" ng-model="program.title"></br>
<input type="text" placeholder="Program Focus" ng-model="program.focus"></br>
<input type="text" placeholder="Program Description" ng-model="program.desc"></br>
<button ng-click="addWeek()"> add week</button>
<div ng-repeat="week in program.weeks">
<input type="text" placeholder="Name the week" ng-model="week.name">
<input type="text" placeholder="Describe It" ng-model="week.desc">
{{ week.name }}</br>
{{ week.desc }}</br>
</div>
<button ng-click="addProgram()"> add program</button>
</div>
</div>
app.js
var myModule = angular.module("trainercompare", ['ui.bootstrap']);
function programsController($scope, $http) {
$scope.program = {
weeks: [{
}]
};
$scope.addWeek = function() {
$scope.program.weeks.push(
{
}
);
};
function isDefined(x) {
var undefined;
return x !== undefined;
}
$scope.addProgram = function() {
var program = {
title: $scope.program.title,
focus: $scope.program.focus,
desc: $scope.program.desc,
weeks: []
};
angular.forEach($scope.program.weeks, function(week, index){
var weekinfo = {
name: week.name,
desc: week.desc
};
program.weeks.push(weekinfo);
});
$http.post('/programs', program).success(function(data, status) {
if(isDefined(data.errors)) {
console.log(data.errors);
}
if(isDefined(data.success)) {
console.log(data.success);
}
});
};
}
Looks to me like you've got a good grasp on it. The addWeek code looks correct. The extra data you see when you console.log your model is some of Angular's internal stuff to track bindings. When you post that to your server it should be cleaned up by Angular.
Angular has a JSON function that removes all of the hash values and other 'angular' things from your JSON. That's why they start with a $ so it knows to remove them.
This happens automatically when you use $http, it's in the documentation here:
If the data property of the request configuration object contains an object, serialize it into JSON format.
Since Angular will clean up the hashes and things, you don't need to "rebuild" the model when you're posting it... just set data to $scope.program and remove 70% of the code in $scope.addProgram.
To learn more specifically how Angular cleans up the JSON, look at this answer: Quick Way to "Un-Angularize" a JS Object

On click How can I cycle through JSON one by one in AngularJS

Creating my first directive as an exercise in angular —making more or less a custom carousel to learn how directives work.
I've set up a Factory with some JSON data:
directiveApp.factory("Actors", function(){
var Actors = {};
Actors.detail = {
"1": {
"name": "Russel Brand",
"profession": "Actor",
"yoga": [
"Bikram",
"Hatha",
"Vinyasa"
]
},
"2": {
"name": "Aaron Bielefeldt",
"profession": "Ambassador",
"yoga": [
"Bikram",
"Hatha",
"Vinyasa"
]
},
"3": {
"name": "Adrienne Hengels",
"profession": "Ambassador",
"yoga": [
"Bikram",
"Hatha",
"Vinyasa"
]
}
};
return Actors;
});
And an actors controller:
function actorsCtrl($scope, Actors) {
$scope.actors = Actors;
}
And am using ng-repeat to display the model data:
<div ng-controller="actorsCtrl">
<div ng-repeat="actor in actors.detail">
<p>{{actor.name}} </p>
</div>
<div ng-click="next-actor">Next Actor</div>
</div>
1) How do I only display the actor's name in the first index of my angular model actors.detail?
2) How do I properly create a click event that will fetch the following index and replace the previous actor.name
User flow:
Russell Brand is Visible
click of next-actor ->Russell Brand's name is replaced with Aaron Bielefeldt
Since you only want the current user, the ng-repeat is not what you want to use, since that would be for each element in the data;
You would want to keep track of the index you are looking at in the scope, and increment that.
<div ng-controller="TestController">
{{data[current].name}}
<div ng-click="Next();"> NEXT! </div>
</div>
Where in the controller we also have these set up, where data is your actors:
$scope.current = 0;
$scope.Next = function() {
$scope.current = ($scope.current + 1) % $scope.data.length;
};
Here's a fiddle where it's done.
I would change my serivce to return a single actor and maintain the index in the controller.
something like this. This is an incomplete solution - you need to take care of cycle etc...

Categories