Using Node (API) to display data in Angular - angularjs

I am still new to the concept of MEAN Stack and right now i am trying to display a list that I get from the Asana API in a simple website that I made. My issue is that in order to get the list that I need from Asana I use nested functions and I have no clue how to send the result to my frontend.
var callback = function() {console.log("test")};
client.projects.findAll(callback).then(function(projects) {
projects.data.forEach(function(project){
var id = project.id;
var name = project.name;
console.log(name);
});
});
If I run the program I do get the list that I want inside my console and would like to know how to display the list from index.html file. Basically how to send the name variable to the frontend.

You need to insert your values in your $scope, for example:
client.projects.findAll(callback).then(function(projects) {
$scope.projects = projects;
});
and then in your HTML use an ng-repeat to display the values, for example:
<div ng-repeat="project in projects | track by $index>
<span>{{project.value}}</span>
</div>
This way, you'll create a div for every project element inside your array, displaying his property .value (but you can substitute .value with any of your properties) with the brackets notation {{ }}

Related

Creating <td> directive with Angular 1.5

I am trying to make an Angular 1.5 directive work within an ng-repeat for a table. A few things I need this to do (and please, if I am going at this the completely wrong way, let me know):
1) Update the html whenever new results are provided. Most importantly, the link function gets called once, with an empty result, and never called again. So, my table is blank. Always.
2) Inside the 'template' of the directive, I reference the controller's name and a method which is type coupling. Is the 'right' way to do this?
Here's my code snippets...
module-a.view.html:
<table>
<tr ng-repeat="(ii,result) in moduleACtrl.results">
<td>This is a normal TD</td>
<td-result result="{{result}}" ctrlName="moduleACtrl"></td-result>
</tr>
</table>
UPDATED
common.td-result.directive.js
(function(){
'use strict';
/* global angular */// ESLINT
angular.module('common').directive('tdResult',Directive);
Directive.$inject = ['$compile'];
function Directive($compile){
return {
restrict : 'E',
scope : {
result : '#',
ctrlName : '#'
},
template: '<td>{{result.prop1}}</td>\
<td>{{result.prop2}}</td>\
<td>{{result.prop3}}</td>\
<td><div ng-click="ctrlName.doSomething()">Something Goes Here {{ctrlName}}</div></td>'
};
}
})();
After reading a number of related questions on StackOverflow, and re-reviewing Angular's Directives documentation, I cannot figure out how to do what I want.
The overall context that got me here is that I have an OpenLayers 3 map, displaying result data from a query. I have the result data on the map interactively displaying result data when you click on it, like this: http://openlayers.org/en/latest/examples/getfeatureinfo-image.html
The difference though, is that I am using Angular 1.5. I have a ModuleA with a controller and view that house the map. I have another ModuleCommon that houses a service that handles creation of the map object and hands it to ModuleA.controller (or any controller who wants the map service). So, now, I have to create an interface for the map service that can generically handle displaying data to any client who wants to render said data.
I decided this was all a bad idea and that I need to step way back. First, the map object should not be responsible for displaying the data. The map is responsible for handling the 'singleclick' event and getting me a feature.
So, I decided that the controller, which instantiates the map object via the map service, will simply be responsible for creating and sending a callback to the map object so the map object knows what it's client wants on a singleclick. The getFeature is the map object's responsibility, and what to do with the feature's id is the client's (i.e. controller's) responsibility.
Whew!
Map code:
map.on('singleclick',function(event){
map.forEachFeatureAtPixel(event.pixel,function(feature){
callback(feature.getId());
});
});
Controller Code:
...
function mapCallback(someId){
var elem = angular.element('#info');
if ( someId === undefined ) {
elem.slideUp(); // Hide element
} else {
for (var data, ii = 0, len = vm.dataList.length; ii < len; ii++) {
data = vm.dataList[ii];
if ( someId === data.property ) {
vm.currentData = data;
$scope.$apply();
elem.slideDown(); // Show element
break;
} else {
elem.slideUp(); // Hide element
}
}
}
}
...
1) The Map is de-coupled from the data pertaining to the feature.
2) The Controller controls what happens when the map selects its data.
3) The HTML stays in the Controller's associated Component's templateUrl where it belongs!

Using ng-repeat with the Pokeapi

I'm trying to get the data for two random pokémon from the Pokéapi. I can grab the data fine, but my angular $scope variables are overwriting the first pokémon with the second pokémon, instead of storing both:
$http.get(endPoint)
.then(function(res){
$scope.pokemonName = res.data.name; // only one 'pokemonName' in $scope
});
You can visually see the pokémon being loaded and displayed incorrectly (two identical pokémon instead of two different ones) in this Plunker example.
I could manually declare two separate $scope variables, eg:
$scope.pokemonNameOne;
$scope.pokemonNameTwo;
But I want to use ng-repeat in the HTML markup, like this:
<div class='pokemon' ng-repeat="pokemon in pokemonPair">
<h2 class='name'>{{ pokemonName }}</h2>
<img src='{{ pokemonImage }}' />
<!-- etc -->
</div>
I feel like what I should be doing, is looping through the required data from the API, then pushing it into a new array of my own creation, and then using my new array in combination with ng-repeat in order to display the two random pokémon. However, I'm unsure as to whether this is an overly convoluted solution. Should I really be re-creating the API data in my own array? It feels like that would be reinventing the wheel. However, I'm not sure how else to solve this problem besides 'Don't use ng-repeat', which isn't a route I want to go down if I can help it, as I'm trying to learn Angular.
Should I be pushing the API data into an array of my own making in order to display it correctly, or is there a smarter way to use ng-repeat?
You are replacing the existing variables, instead of pushing it to an array. Do something like this:
function getStats(pokemonIndex){
var pokemon = $scope.pokemonPair[pokemonIndex];
$http.get(pokemon.endPoint)
.then(function(res){
pokemon.pokemonName = res.data.name;
pokemon.pokemonExperience = res.data.base_experience;
pokemon.pokemonImage = res.data.sprites.front_default;
pokemon.pokemonStats = res.data.stats;
console.log("pokemonName = " + pokemon.pokemonName);
});
}
and call it like this:
function populateStats(){
for (var i = 0; i < $scope.pokemonPair.length; i++){
getStats(i);
}
}
See this edited plunker
Also notice that I have changed the pokemonPair property to be an array of objects, to be able to add the properties to it and use the ng-repeat.
Here is a working plunker:
https://plnkr.co/edit/c5seK6wr8rQjMAj5GZA9?p=preview
Just push the response from the api into an array and databind everything from there!
function getStats(endPoint){
$http.get(endPoint)
.then(function(res){
$scope.pokemons.push(res.data);
console.log("pokemonName = " + $scope.pokemonName);
});
}
You have to read about Arrays in JavaScript. Your question doesn't actually related to Angular itself.
$scope.pokemonNames = [];
$http.get(endPoint)
.then(function(res){
var pokemon = {};
pokemon.name = res.data.name;
pokemon.attribute = res.data.attribute;
$scope.pokemonNames.push(pokemon); // then iterate over pokemonNames array in ng-repeat.
});

ngRepeat seems to use a random order instead of order given

I have a json containing objects originating from my Symfony controller.
I need to loop over the objects like so
<li data-ng-repeat="course in courses"></li>
In my app controller I do this
$scope.courses = {{ courses | serialize('json', serialization_context().setGroups(['identification', 'courseListing', 'portalOverview'])) | raw }};
The order is okay when I check the scope variable 'courses' with the ng-inspect browser plugin.
Screenshot : http://i.imgur.com/pKy00uo.png
But still the loop seems kinda random. The last object keeps getting placed after the 2nd child.
Any ideas? Need more info, just ask. Thanks!
Okay, so it seems Angular doesn't handle objects too well when given to ng-repeat.
I transformed my object of objects to an array of objects and the objects were rendered in the correct order.
var arrCourses = [];
$.each($scope.courses, function(index, obj){
arrCourses.push(obj);
});
$scope.courses = arrCourses;

passing values from view to controller globally

I am working on angularjs and faced a problem while displaying the details of each record on another page.The list of records are displayed using controller and each record has a link, on click of which i want to pass the id of the selected item to the same controller so that using this id I can display respective data.This is what i have done
<tr ng-repeat="doctor in doct| filter:name" ><td><a href="" ng-click="showid(doctor.contactId)" >&gt</a><td></tr>
this is the code in js file:
app.controller('Mycontroller', function Mycontroller($scope,$http){
$scope.showid=function(idPassedFromNgClick){
var v=idPassedFromNgClick;
console.log(v);
$http.get('scripts/doc.json').success(function(data){
$scope.doct=data;
};
});
});
here i am passing the id in function showid. In console i am able to get the respective id.But i cant use it outside the scope of my function(showid).Plz suggest me a way to get it globally so that i can use it in details page.

How can I fill select2 data dynamically using angularjs

My case is that I want to use the createSearchChoice feature of the Select2 widget. So I found out I need to use an html input element instead of a select element and so I cannot use ng-repeat to populate the select2 widget. I find out there is a 'data' option and have been able to populate the select2 widget with static data, but not when I've tried to fill it dynamically.
What works:
html:
<input class='select2' ui-select2='sel2props' type='hidden'>
in the controller:
$scope.sel2props = {
createSearchChoice: ...
data: [
{ id: 0, text: 'yabba' }
etc
]
};
But if I try to set data to a variable which I can then set to whatever the database feeds me the widget isn't populated.
data: $scope.data;
function to retrieve data {
$scope.data = retrieved data;
}
the retrieved data is exactly in the way specified.
If i set up a button to append the data key it will work:
$scope.appenddata = function () {
$scope.data.push({id:1, text: 'anot'});
};
So I'm thinking it's a timing issue and I try $digest and $apply but they don't work in controllers. I tried to set up a directive and actually can do simple widgets, but not select2, so I was hoping not to go down that path, well that is to say I went down that path and drowned. If anyone could help out that would be great.
The solution is straight forward. Just push the elements onto the select2 data array rather than referencing another array.
function (result) {
$scope.lookupOptions.data.length = 0; // remove old items
angular.extend($scope.lookupOptions.data, result.data); // add new items
}
A trick I've recently made use of is to use Select2's query option to pass in your latest data on demand.
I've put together an example, wrapped in a custom directive. See this Plunk.

Resources