Right now we are facing an issue in a controller that calls a DataService (Parse), the problem is that this code does not work:
function MainCtrl($scope, DataService, $location)
{
$scope.actionList = function() {
// Call the service and fetch the list of signatures that match the given action ID
DataService.getActions(function (results) {
$scope.$apply(function () {
// Apply the results to the signatureList model so it will refresh the table in the view
$scope.actionList = results;
});
});
};
}
I put a breakpoint in the DataService line but it doesn't get hit, but if I implement the Ctrl in this way it does get call and It works!!:
function MainCtrl($scope, DataService, $location)
{
// Call the service and fetch the list of signatures that match the given action ID
DataService.getActions(function (results) {
$scope.$apply(function () {
// Apply the results to the signatureList model so it will refresh the table in the view
$scope.actionList = results;
});
});
}
Any idea why is this happening??
Apart from that once is working (with the second implementation) I would like to show a property of the activity, if I try to get the property like this it does not work:
<div id="wrapper"><div id="scroller">
<div ng-controller="MainCtrl">
<ul id="thelist">
<li ng-repeat="action in actionList">{{action.get('Action')}}</li>
</ul>
</div>
</div></div>
But if I try to get the whole object like {{action}} I can actually see all the entries.
Change the controller to
function MainCtrl($scope, DataService, $location) {
$scope.getActionList = function() {
DataService.getActions(function(results) {
$scope.$apply(function() {
$scope.actionList = results;
});
});
};
$scope.getActionList();
}
Then if you want to reload actionList call getActionList()
Any idea why is this happening??
In your first example, you are simply defining a function named actionList on object $scope. Defining a function won't execute it (see #Arun's answer).
To show your data in the view, you can use normal JavaScript dot notation. If an action object looks like this:
{ prop1: 'property 1', prop2: [1, 2], prop3: { name: 'Javito'} }
You could write the view/HTML as follows:
<ul id="thelist">
<li ng-repeat="action in actionList">
prop1: {{action.prop1}}<br>
prop2: {{action.prop2[0]}} {{ action.prop2[1] }}<br> <!-- or use another ng-repeat here -->
prop3.name: {{action.prop3.name}}
</li>
</ul>
Related
I am using a custom view directive inside a ng-repeat list like this:
//Directive
app.directive("card", function () {
return {
restrict: "E",
templateUrl: "views/card.html"
};
});
...
//List
<card ng-repeat="card in cards = main.data.getCards() | filter: sidebar.search() | orderBy: ['isPinned',$index]:true track by $index"
ng-if="content.checkCard(card)">
</card>
main.data is a reference to a service, where the data is being stored.
Here is a simplified version:
app.service('data', function ($http, engine) {
var cards = [];
...
return {
getCards: function () {
return cards;
},
setCards: function (data) {
cards = data;
engine.save("cards", cards);
},
When the data changes through the setCards() method, my list shows only empty elements. If I use the exact same html code inside my ng-repeat directly however, everything works fine. What can I do?
I have my page with element like this
<div ng-app="myApp" class="ng-cloak" ng-controller="MyController as ctrl">
<div class="item" ng-repeat="i in ctrl.items">
<h3>Some text...</h3>
<p ng-bind="i.id"></p>
<button ng-click="alertValue(i.id)">DETAILS</button></p>
</div>
</div>
My controller looks like this and has a method
'use strict';
App.controller('MyController', ['$scope', 'Item', function ($scope, Item) {
$scope.alertValue = function (id) {
alert('clicked:' + id);
}
}
Which works fine, I get the alert with the id. But how do I send this id from controller to my service? I tried following few tutorials, but they are all different and I got completly lost in it. Can anyone explain this to me in a simple way and show how to do this?
May be I need to provide some additional info? Thanks.
I try not to use scope so I would create a function for that click on my controller. Then it's just a matter of doing what you want with it.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
angular.module('my-app', [])
.service('Items', function() {
return {
doWork: function(id) {
console.log(id);
}
};
})
.controller('ItemsCtrl', function(Items) {
var vm = this;
vm.items = [
{ id: 1, name: 'Foo' },
{ id: 2, name: 'Bar' },
{ id: 3, name: 'Baz' },
];
vm.doWork = function(id) {
Items.doWork(id);
};
});
</script>
<div ng-app="my-app">
<div ng-controller="ItemsCtrl as ctrl">
<ul>
<li ng-repeat="item in ctrl.items">
{{item.name}}
<button ng-click="ctrl.doWork(item.id)">Do Work</button>
</li>
</ul>
</div>
</div>
You have to use $http service. $http service facilitates communication with the remote HTTP servers.
$http service use then method in order to attach a callback.
The then() method takes two arguments: a success and an error callback which will be called with a response object.
Using the then() method, attach a callback function to the returned promise.
Something like this:
app.controller('MainCtrl', function ($scope, $http){
$http({
method: 'GET',
url: 'api/url-api'
}).then(function (success){
},function (error){
});
}
See reference here
Shortcut methods are also available.
$http.get('api/url-api').then(successCallback, errorCallback);
function successCallback(response){
//success code
}
function errorCallback(error){
//error code
}
You have to inject the service inside controller to pass some data to it.
app.controller.js
App.controller('MyController', ['$scope', 'ItemService', function ($scope, ItemService) {
$scope.alertValue = function (id) {
ItemService.id = id;
}
}
Please refer this for more information on creating and registering a service in angular.
Is it possible queuing ng-init?
Generally, in first init I want to add JSON file to prototype vars (array) and in another init depending on the params I want to skip getJsonData() or add other JSON file to prototype.
function init(param) {
console.log("startInit");
// big JSON file
var promise = getJSON(param);
return promise.then( function() {
//some func
console.log("finish");
return true;
});
};
function getJSON(param) {
var deferred = $q.defer();
console.log("startInitDataInner");
someService.getJsonData(param).then(function(data) {
// some code
console.log("endInitDataInner");
deferred.resolve();
}, function(error) {
deferred.reject();
});
return deferred.promise;
};
in view ng-init
ng-init="init(param)"
ng-init="init(param)"
// ...
and log:
startInit
startInitDataInner
startInit
startInitDataInner
endInitDataInner
finish
endInitDataInner
finish
//..
Edit:
Generally, I want to create something like plugin in jQuery. I have this code:
<div ng-controller="parentController as parent">
<div ng-controller="childController as child" ng-init="child.init(parent.data)"></div>
</div>
<div ng-controller="parentController as parent">
<div ng-controller="childController as child" ng-init="child.init(parent.data2)"></div>
</div>
and configurable part by user:
angular.module('myApp').controller('parentController', ['$scope', function($scope) {
this.data = {
config: {
lang: "en",
title: "title"
}
};
this.data2 = {
config: {
lang: "pl",
title: "title2"
}
};
}]);
ng-init update api:
angular.extend(this, parent.data);
Do you have any ideas how I should do it differently?
Well, if you are working with angular, you use controllers. What is controller itslfmin general meaning? Right, its a constructor function. The main word here is function. What does function in general? Run the code inside.
So, just place your initial logic at the beggining of controller code (but without wrapping it as a separate function) and it will run just in time your controller will be resolved by angular resolver.
var controller = function () {
// vars, costs, etc.
console.log("startInit");
// big JSON file
var promise = getJSON(param);
return promise.then( function() {
//some func
console.log("finish");
return true;
});
};
I'm writing an angular 1.5.0-rc0 application using bootstrap for a nav bar component.
I want to show the user an added items to his navigation bar if his user group id is 1.
first I created a service:
app.factory('UserService', function() {
return {
userGroupId : null
};
});
I created the nav bar as a directive, so i included it in the main html file
<nav-bar></nav-bar>
and the nav-bar directive code:
(function () {
angular.module('myalcoholist').directive('navBar', function () {
return {
restrict: 'E',
templateUrl: 'views/nav.html',
controller: ['$scope','$auth', 'UserService',function ($scope,$auth,UserService) {
$scope.user=UserService;
$scope.isAuthenticated = function()
{
return $auth.isAuthenticated();
};
}]
}
});
})();
as you can see I set $scope.user as the returned object from UserService.
in my login controller, after a successful login I set the userGroupId.
angular.module('myalcoholist').controller('LoginController',['$scope','$auth','$location', 'toastr','UserService',function ($scope,$auth,$location,toastr,UserService) {
$scope.authenticate = function (provider) {
$auth.authenticate(provider).then(function (data) {
var accessToken = data.data.token;
apiKey=accessToken;
UserService.userGroupId=data.data.user_group_id;
...
now.. my nav-bar template file is as the following code:
<li ng-show="user.userGroupId == 1">
Admin Drinks
</li>
even after the authentication, when I uset userGroupId to 1 the element is still not shown.
any ideas?
update
I debugged and noticed that UserService.userGroupId is still null. so
I changed the UserService to have the following code:
app.factory('UserService', function() {
var user = {userGroupId:null};
return {
setUserGroupId: function (userGroupId) {
user.userGroupId=setUserGroupId;
},
getUserGroupId: function () {
return user.userGroupId;
}
};
});
in my LoginController I now try to execute setUserGroupId:
angular.module('myalcoholist').controller('LoginController',['$scope','$auth','$location', 'toastr','UserService',function ($scope,$auth,$location,toastr,UserService) {
$scope.authenticate = function (provider) {
$auth.authenticate(provider).then(function (data) {
var accessToken = data.data.token;
apiKey=accessToken;
UserService.setUserGroupId(data.data.user_group_id);
...
when I debug i see that userService is an object with two functions as I defined, but when the javascript chrome debugger tries to execute this line:
UserService.setUserGroupId(data.data.user_group_id);
I get the following error:
ReferenceError: setUserGroupId is not defined
at Object.setUserGroupId (app.js:21)
at login-controller.js:12
at angular.js:15287
at m.$eval (angular.js:16554)
at m.$digest (angular.js:16372)
at m.$apply (angular.js:16662)
at g (angular.js:11033)
at t (angular.js:11231)
at XMLHttpRequest.v.onload (angular.js:11172)
I have created a fiddle showcasing your requirement (as close as possible), and it seems to work fine.
http://jsfiddle.net/HB7LU/21493/
My guess is that you aren't actually setting the value when you think you are, and will likely require some debugging. Here is the code for brevity.
HTML
<div ng-controller="MyCtrl">
<div ng-click="clicked()">
Click ME, {{user.value}}!
</div>
<test-dir></test-dir>
</div>
JS
angular.module('myApp',[])
.service('TestService', function(){
return {
value: 2
};
})
.directive('testDir', function(){
return {
restrict: 'E',
template: '<div ng-show="user.value === 1">Here is some text</div><div>Some more always showing</div>',
controller: function ($scope, TestService) {
$scope.user = TestService;
}
};
})
.controller('MyCtrl', function($scope, TestService){
$scope.user = TestService;
$scope.clicked = function(){
TestService.value = 1;
};
});
Overview
I am building an app (running on MAMP) that holds contact information that will expand to hold more data such as project name & deadline, once this part is functional.
Questions
When the user visits /projects.php#/project/ I would like them to see a list of all the project names with a link to their detail page.
How should I write the following to access all of my data?
Do I need the .json at the end?
What does the #id do?
return $resource('data/project.json/:id', {id: '#id'});
When the user visits /projects.php#/project/a-gran-goodn I would like them to see the details about this project(for now, just the name & address).
How should I write the following to return my data by Id?
$scope.project = $routeParams.id ? Project.get({id: $routeParams.id}): new Project();
plunkr file
http://plnkr.co/edit/7YPBog
project.json
This file lives on http://localhost:8888/angularjs/ProjectsManager/data/project.json
[
{ "address" : [ " 3156 Dusty Highway",
" Teaneck New Jersey 07009-6370 US"
],
"id" : "a-gran-goodn",
"name" : "Grania Goodner",
"phone" : " (862) 531-9163"
},
{ "address" : [ " 62 Red Fawn Moor",
" Rodney Village West Virginia 25911-8091 US"
],
"id" : "b-aime-defranc",
"name" : "Aimery Defranco",
"phone" : " (681) 324-9946"
}
]
app.js
var projectsApp = angular.module('projects', ['ngResource']);
projectsApp.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'ProjectListCtrl',
templateUrl: 'partials/projectlist.html'})
.when('project/:id', {
controller: 'ProjectDetailCtrl',
templateUrl: 'partials/projectdetail.html'
})
.otherwise('/');
});
projectsApp.factory('Project', function($resource) {
return $resource('data/project.json/:id', {id: '#id'});
});
projectsApp.controller('ProjectListCtrl', function(Project, $scope) {
$scope.projects = Project.query();
console.log($scope.projects);
});
projectsApp.controller('ProjectDetailCtrl', function(Project, $routeParams, $scope) {
$scope.project = $routeParams.id
? Project.get({id: $routeParams.id})
: new Project();
});
partials/projectlist.html
Add new item
<ul class="unstyled">
<li ng-repeat="project in projects">
<div class="well">
<h2><small>{{project.id}}</small> {{project.name}}</h2>
View Info for {{project.name}}
</div>
</li>
</ul>
partials/projectdetails.html
<h3>Information</h3>
<p>Name: {{project.name}}</p>
<p>Phone Number: {{project.phone}}</p>
<p ng-repeat="line in project.address">{{line}}</p>
index.php
<?php
header('Access-Control-Allow-Origin: *');
?>
<!doctype html>
<html ng-app="projects">
<head>
<meta charset="utf-8">
<title ng-bind="title" ng-cloak>Restaurant —</title>
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
</head>
<body ng-controller="ProjectListCtrl">
<a class="brand" href="#">Projects Manager</a>
<div id="app-container" class="container-fluid">
<div class="row-fluid">
<div class="span12" id="main" ng-view>
</div><!--/.span12-->
</div><!--/.row-fluid-->
<footer>Copyright Projects © 2013</footer>
</div><!--/.container-->
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<!-- Don't forget to load angularjs AND angular-resource.js -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular-resource.js></script>
<!--Controllers-->
<script src="app.js"></script>
</body>
</html>
Since you can't query against a raw JSON file like you can with RESTful-style URLs (which is what $resource is built to do), you can instead get a copy of the JSON and then build your own query, get, etc. that looks at the data and returns the right thing. It's a bit tricky because you also want to support new Project, which doesn't really make sense when using a file-backed store, but this example supports it:
projectsApp.factory('Project', function($http) {
// Create an internal promise that resolves to the data inside project.json;
// we'll use this promise in our own API to get the data we need.
var json = $http.get('project.json').then(function(response) {
return response.data;
});
// A basic JavaScript constructor to create new projects;
// passed in data gets copied directly to the object.
// (This is not the best design, but works for this demo.)
var Project = function(data) {
if (data) angular.copy(data, this);
};
// The query function returns an promise that resolves to
// an array of Projects, one for each in the JSON.
Project.query = function() {
return json.then(function(data) {
return data.map(function(project) {
return new Project(project);
});
})
};
// The get function returns a promise that resolves to a
// specific project, found by ID. We find it by looping
// over all of them and checking to see if the IDs match.
Project.get = function(id) {
return json.then(function(data) {
var result = null;
angular.forEach(data, function(project) {
if (project.id == id) result = new Project(project);
});
return result;
})
};
// Finally, the factory itself returns the entire
// Project constructor (which has `query` and `get` attached).
return Project;
});
You can use the results of query and get like any other promise:
projectsApp.controller('ProjectListCtrl', function(Project, $scope) {
$scope.projects = Project.query();
});
projectsApp.controller('ProjectDetailCtrl', function(Project, $routeParams, $scope) {
$scope.project = $routeParams.id
? Project.get($routeParams.id)
: new Project();
});
Note the change to Project.get($routeParams.id); also, the updated Plunker also fixes a problem in your $routeProvider configuration.
This is all demonstrated here: http://plnkr.co/edit/mzQhGg?p=preview
i will paste here a generic code i use to fetch json from your local or a remoteserver maybe it will help you:
it uses a factory that you can call when you need it.
app.factory('jsonFactory', function($http) {
var jsonFactory= {
fromServer: function() {
var url = 'http://example.com/json.json';
var promise = $http.jsonp(url).then(function (response) {
return response.data;
});
return promise;
},
hospitals: function() {
var url = 'jsons/hospitals.js';
var promise = $http.get(url).then(function (response) {
return response.data;
});
return promise;
}
};
return jsonFactory;
});
Then when you need to call it:
function cardinalCtrl(jsonFactory, $scope, $filter, $routeParams) {
jsonFactory.hospitals().then(function(d){
$scope.hospitals=d.hospitals;
});
jsonFactory.fromServer().then(function(d){
$scope.fromServer=d.hospitals;
});
}