I've been struggling with this the past few Hours and I don't know what to do about it. I am doing an AngularJS application and I use angular-timer Directive.
http://siddii.github.io/angular-timer/
It works perfect when I dynamically assign TimerValue value to the end-time attribute in ng-repeat. But it fails when I use it in My Details page which is using routeParams
<timer end-time="itemDetail.startDate">
so on the Detail page when the user click somewhere he is getting redirected to /someurl/1 The page loads fine the iMages the text everything is working fine. But the timerValue is showing NaN everywhere here is the app structure I've been using
JSON data
[
{
"id" : "1",
"productTitle" : "Motorola 156 MX-VL",
"imgUrl" : "app/assets/images/laptop.png",
"itemPrice" : "170",
"startDate" : 1431249465000
}
]
Page controller
app.controller('detailsController', ['$scope', '$routeParams','itemsService',
function($scope, $routeParams,itemsService) {
itemsService.getItemById($routeParams.itemId).then(function(data){
$scope.itemDetail = data;
});
}]);
The factory
app.factory('itemsService', ['$http','$filter', function($http, $filter){
var itemsService = {
getAllItems: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('app/jsons/items.json').then(function (response) {
return response.data;
});
// Return the promise to the controller
return promise;
}, getItemById : function(id) {
var promise = $http.get('app/jsons/items.json').then(function (response) {
return $filter('filter')(response.data, {id: id})[0];
});
// Return the promise to the controller
return promise;
}
};
return itemsService;
}]);
And in the View I'm using it like this
<div class="large-12 columns" >
Remaning time: <timer end-time="startDate">{{days}} Days, {{hours}} Hours, {{minutes}} Minutes, {{seconds}} Seconds.</timer>
</div>
The timer works if I put the Timestamp directly in the "end-time" attribute and it also work if I assign the Value directly in the controller
$scope.startDate = 1431249465000;
But it doesn't work if I do it like this:
<timer end-time="itemDetail.startDate">
Why is this happening?
you needs eval expression for end-time attributes
<timer end-time="{{itemDetail.startDate}}">
Okay guys. I found a solution that worked for me and its pretty easy though. It seems that the problem is related with the way how angular execute its methods. When i assign a filtered object to the $scope.itemDetail= filteredObj. And when i try to use the itemDetail.startDate in the html the value does not get resolved correctly and i see the NaNs. So this might work correctly when i hook up the Rest api which is still under development but for now i am using mockup jsons with dummy data, and god nows what is going on behind the scenes with Angular. The solution i used was simply to use ng-repeat instead of directly accessing the object property from the html. And it worked.
The solution
i added a ng-repeat directive to the parent div that holds my Item details. And simply accessing the properties like this
<div ng-repeat="item in itemDetails">
{{item.name}}
Remaning time: <timer end-time="item.StartDate">{{days}} Days, {{hours}} Hours, {{minutes}} Minutes, {{seconds}} Seconds.</timer>
</div>
And in this case it works as it suppose to either way or another in my itemDetails object array i have only one Object since i filter the data according the ID that is passed from the $routeParams
Related
I want to know how to dynamically change an $http call so that the $http request URL differs based on the element that is clicked in an ng-repeat list. But I'm stuck.
Currently, I have an ng-repeat set up on my index page:
<div ng-repeat="team in nt.getStandings">
<h2>{{team.team_name}}</h2>
<p>Team ID = {{team.team_id}}</p>
</div>
The variable getStandings is taken from an API via an $http call. Like so:
In StandingsService
return $http.get(
'http://api.com/standings/1005?Authorization=xxxx'
)
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
And then StandingsService is attached to the getStandings variable in my controller.
"1005" is a property which calls a specific array, in this case a particular sporting competition, from an array of competitions.
So, on my index page I'm using ng-repeat to list all teams within that competition.
As you can see on the html above, I have linked each team so that it dynamically generates a URL which appends the team_id to the end, which using $routeParams I define as the variable whichTeam.
Team Details Page
<h1>Dynamic Team ID = {{whichTeam}}</h1>
This works fine, the team ID is generated dynamically according the team that is clicked.
Just like 'StandingsService' above, I have another service called 'TeamService' which makes an $http request to pull team data. Currently though it is set up statically to make a call to one individual team - I want to make the service take in the whichTeam variable so that the call changes depending on which team was clicked.
This is the static team $http request (I've broken the URL apart and concatenated to make it clearer):
return $http.get(
'http://api.com/team/' + '16110' + '?Authorization=xxxx'
)
I want the 16110 part, which refers to ONE team, to be a the whichTeam variable, allowing it to pull in the correct individual team data, but I don't know how to write this (or indeed if it's possible).
I hope I've been clear - happy to clarify further if needed. Thanks in advance.
Make a factory:
app.factory("DataService", ["$http", function($http) {
return {
getTeamDetailsById: function(teamId) {
return $http.get('path/to/api' + teamId + '?Auth=xxxx')
}
};
}]);
Use it in a controller:
app.controller("MainCtrl", ["$scope", "DataService", function($scope, DataService) {
$scope.teamDetails = {};
$scope.getTeamDetailsById = function(event, teamId) {
//prevent click navigation
event.preventDefault();
//call factory service
DataService.getTeamDetailsById(teamId).then(function(response) {
//success callback
$scope.teamDetails = response.data;
}, function(response) {
//an error has occurred
});
}
}]);
In the ng-repeat element:
<div ng-repeat="team in teams">
<a href ng-click="getTeamDetailsById($event, team.team_id)">{{team.team_name}}</a>
</div>
The above assumes you have only one state and are storing in only one controller. If you want to use different states usving $stateProvider, then you'd have to use parameters, by making use of ui-sref and passing in team Id.
If indeed you are using $states and parameters, do this:
<a href ng-click="goToState($event, team.team_id)">{{ team.team_name }}</a>
$scope.goToState = function(e, teamId) {
$state.go("teamDetailsState", { "teamId": teamId });
}
Well, I'm making a switch using Angular Material switch, but it's not starting with its initial state as you can see on the picture. The label aside it is the value of it.
And as you can see, the switch starts deactivated from the beginning.
To Start, I'm getting the results from a get request, and putting it into an array.
$scope.questions = [];
The value I'm showing on the picture can be false or true.
On the md-switch, I've referenced directly to the property inside of the array.
<tr ng-repeat="quest in questions">
<td><md-switch ng-model="quest.status">{{quest.status}}</md-switch></td>
</tr>
How can I set the value initially for the switch?
This is a Codepen with a test.
http://codepen.io/anon/pen/BjzpNN
but this seems awkward tho. Doing my example it works fine, but with my development environment, it doesn't work.
This is the console.log of my array, I'm getting this as a get request using $resource.
Well, what is the problem?
Edit2:
Even more awkward, using the properties ng-true-value and ng-false-value the switch doesn't get the initial state.
I updated your JavaScript below, to use a service to get the results. However, I am just returning the hard coded data from your sample. You should change the service to go and fetch your data. The service will be used as a promise, and will return when complete.
(function(){
var app = angular.module('test', ['ngMaterial'])
.service('testService', function() {
// This should be modifed to then call your external API to get the data instead of hard coded results
var questions = [
{ name : "teste", status : true},
{ name : "teste2", status : false},
{ name : "teste3", status : true}
];
return questions;
})
.controller('testController', ['$scope', 'testService', function($scope, testService) {
$scope.questions = [];
$scope.questions = testService; // Use service to get data, will update questions when promise returns.
}]);
}())
There is no check on the data loading, so your screen will be empty until the service returns data. However, when the service returns data, your view should be updated.
As your CodePen showed, you do not need the ng-true-value/ng-false-value, just the ng-model to list the field to get the setting from. The ng-true-value is the value to be set when you toggle the switch (Angular md-switch docs if you want something different from True/False (say A/B).
You might also need to use ng-disabled if you want to protect the switches from changing.
I'm trying to get my first ASP.NET Webforms and AngularJS app up and running, but I'm struggling...
I created a blank, new ASP.NET 4.5.1 webforms app, and included WebAPI into the mix. I created a sample page for my list of customers, and a standard, EF6-based WebAPI CustomerController : ApiController with all the usual CRUD methods. I tested that WebAPI using Fiddler and low and behold - I get my 8 customers back from my database.
Getting this into AngularJS however has been a bit of a unsuccessful and highly frustrating experience ....
I included AngularJS from NuGet and that seems to have worked - no errors shown or anything, a pile of angular*.js files dumped into my Scripts folder.
I created a basic CustomerList.aspx page based on a master page which includes the <html lang="en" ng-app="TestAngular"> tag.
In order to get the data from the WebAPI service, I created my Angular module, and created a model inside the $scope, and created a service to fetch the data from the WebAPI:
Inside app.js:
var testModule = angular.module('TestAngular', [ ]);
testModule.controller('clientController', function ($scope, clientService) {
$scope.model = [];
clientService.getAllClients(function(results) {
$scope.model.clients = results;
});
$scope.model.clientCount = $scope.model.clients.count;
});
testModule.factory('clientService', function ($http) {
var srv = {};
srv._baseUrl = 'http://localhost:56313';
// Public API
return {
getAllClients: function(callback) {
return $http.get(srv._baseUrl + '/api/Customer').success(callback);
}
};
});
From what limited Javascript understanding I have, this should define a clientService (the testModule.factory() call) that calls my WebAPI URL, gets the JSON back, and the callback function then stuffs those customers retrieved into the $scope.model.clients property, and the $scope.model.clientCount should also be calculated.
My ASPX page looks something like this:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="CustomerList.aspx.cs" Inherits="TestAngular.CustomerList" MasterPageFile="~/Site.Master" %>
<asp:Content runat="server" ID="content" ContentPlaceHolderID="MainContent">
<h2>My customers</h2>
<div class="panel panel-default" data-ng-controller="clientController">
We have a total of {{ model.clientCount }} clients in our database table ...
<div class="list-group" data-ng-repeat="client in model.clients">
<div class="list-group-item">
<span>{{ client.Name }}</span><br/>
<span>{{ client.Name2 }}</span><br/>
</div>
</div>
</div>
</asp:Content>
So the <div> with the data-ng-controller should "connect" that DIV with the AngularJS controller, should load the customers from the WebAPI call, and contain them in the model, which would then be rendered to the ASPX page using the data binding syntax ({{ client.Name }} etc.)
Trouble is: the call to the WebAPI happens and the correct 8 customers are returned, however, when I debug into the Javascript code, the clientCount is always undefined and the ASPX page only shows two empty rows which probably would correspond to customers that have been retrieved - but why only 2, not 8 ??
I'm totally lost and stuck - can anyone spot what I'm doing wrong, what I'm missing here??
You are definately on the right track. At the moment, the problem is down to the clientService getAllClients method.
You should return the promise and then the data will chain through to the controller:
getAllClients: function(callback) {
return $http.get(srv._baseUrl + '/api/Customer').success(callback);
}
You may also want to take a look at the count line:
$scope.model.clientCount = $scope.model.clients.count;
Before the promise is resolved (and the callback is invoked), $scope.model.clients will be undefined. So, I'd expect this line to fail. Also, to get the count of an array, you need length.
You should set the clientCount inside of the callback:
clientService.getAllClients(function(results) {
$scope.model.clients = results;
$scope.model.clientCount = $scope.model.clients.length;
});
Edit:
Typically, it is favoured to use the promise returned by $http. So, the controller would slightly change to:
clientService.getAllClients().then(function(response) {
$scope.model.clients = response.results;
$scope.model.clientCount = response.results.length;
});
And then the service would change to:
getAllClients: function() {
return $http.get(srv._baseUrl + '/api/Customer');
}
Angular uses promises from $q instead of callbacks (for most apis). They make chaining and exception handling much easier.
Also, since, in this case, you know you are handling a promise from $http, you can use the success method in the controller as well:
clientService.getAllClients().success(function(results) {
$scope.model.clients = results;
$scope.model.clientCount = results.length;
});
success unwraps the response and sends only the body through to the callback.
First off, i found the api address from this topic:
Laravel 4 and Angular JS and Twitter Bootstrap 3 Pagination
Now i am working about this, my little script is so:
var app = angular.module('kategori', [
'ngResource',
'apiBaseRoute'
]);
app.factory('Data', ['$resource', 'apiBaseRoute', function($resource, config){
return $resource('http://develop.alexei.me/careers/careers.php?callback=JSON_CALLBACK&page=:page', {
page: 1
}, {
'get': {
method: 'JSONP'
}
});
}]);
app.controller('KategoriListCtrl', function($scope, Data){
$scope.init = function() {
Data.get({}, function(response){
$scope.kategoriList = response.careers;
},function(error){
console.log("HATA VAR" + error);
});
};
});
app.directive('paginate', function(){
return{
scope:{ allData: '=paginate2' },
link: function(scope){
console.log(scope);
}
}
});
And this is the html side :
<div class="col-md-6 col-md-offset-3" ng-controller="KategoriListCtrl" ng-init="init()">
{{kategoriList}}
<div paginate paginate2="kategoriList"></div>
</div>
as you see, console.log(scope) inside directive is shows a lot of things in console, especially i see allData there with lots data, but if i change it to
console.log(scope.allData)
it prints undefined..
i don't understand why. how can i solve this? thanks.
By the time JS reaches your console.log the allData property is undefined (since kategoriList is undefined). kategoriList (and thus allData) is created (and populated with lots of data) asynchronously at a later time.
So, why do you see the data when logging the scope object instead ?
At the time the object is logged it has no property allData (and no data).
But by the time you go over to the console and expand the node and look for the allData property, the property has been added and populated by your AJAX call (using $resource).
It is not clear what you want to do with allData.
If you want to use it in e.g. ng-repeat you don't have to worry: You can use it normally (as if it were defined) and Angular will automatically "pick it up" as soon as it arrives and do stuff.
Yet, if you want (for your own mysterious reasons) to get informed when it is ready, your can use $watch:
scope.$watch('allData', function(newValue) {
if (newValue !== undefined) {
console.log(scope.allData);
}
});
See, also, this short demo.
I'm just starting to play with angularJS, so maybe I'm asking something easy to do, but I can't find the way to do it.
The situation is the following: I have a list that's populated by an ng-repeat taking the values from a scoped controller variable. This variable is loaded on page load by an jsonp call, and this works fine.
The problem comes when I need to reload this list based on another select. For example, if a select 'day' value in the select I need to show some values and when I select 'week' I need to show others (also loaded via ajax).
What I've tried is to have a service that loads the data and returns it, and in the controller have two methods, one for the first load and another for the second one that does $scope.apply with the variable. I then call this second method on select value change (I've done it with jquery to simplify it until I can fix this).
This is part of my HTML
<div x-ng-controller='LeaderboardCtrl'>
<select id='leaderboard-select'>
<option value='day'>day</option>
<option value='week'>week</option>
<option value='month'>month</option>
</select>
<div x-ng-repeat='p in leaderboard'>
<p>{{p}}</p>
</div>
</div>
And this is part of the code that affects this functionality
var lead = angular.module("lead",[]);
function LeaderboardCtrl($scope,$attrs,$http,jtlanService) {
$scope.leaderboard = [];
$scope.period = 'day';
var data = {
period:$scope.period
};
$scope.loadLeaderboard = function(){
myService.loadLeaderboard(data).then(function(leaderboard) {
$scope.leaderboard = [];
$scope.leaderboard.push.apply($scope.leaderboard,leaderboard);
});
}
$scope.reloadLeaderboard = function() {
myService.loadLeaderboard(data).then(function(leaderboard) {
$scope.$apply(function() {
$scope.leaderboard = [];
$scope.leaderboard.push.apply($scope.leaderboard,leaderboard);
});
});
}
$scope.loadLeaderboard()
}
lead.service("myService",["$http", function($http) {
var myService = {
loadLeaderboard : function(data) {
var promise = $http.jsonp("/widget/leaderboardJSONP?callback=JSON_CALLBACK&_="+new Date(),{
params:data,
cache:false,
ajaxOptions: { cache: false }
}).then(function(response) {
return response.data;
});
return promise;
}
};
return myService;
}]);
$("#leaderboard-select").change(function(){
scope.period = $("#leaderboard-select").val();
scope.reloadLeaderboard();
});
Here's a fiddle with the code: http://jsfiddle.net/WFGqN/3/
Your fiddle is riddled with issues:
There's no ng-app in your mark-up
You need to change the second Framework Extensions dropdown to one of the "No wrap" options
Your service needs to be defined above your controller
Your controller is referencing "jtlanService" but you've defined "myService"
Your $http.jsonp call isn't going to work as is, but you could use can use the echo service (see Ajax Requests on the left side) to emulate requests
You can't and shouldn't be using jQuery events to call Angular controllers. You should use ng-change and not $().change (and even if you were using jQuery for event binding, you should be using $().on('change')).
You didn't need to use $scope.$apply in your loadLeaderboard function, since when you're calling it, you were already inside of of an $apply call.
There's no need for 2 load+reload leaderboard methods.
And after all that, you don't actually need jQuery.
Here's a fiddle that fixes things up and I think gets you what you want: http://jsfiddle.net/WFGqN/5/. You'll of course need to fix the service on your end, but you get the idea.
I recommend reading this SO answer: "Thinking in AngularJS" if I have a jQuery background?