How can I use a different sets of initialization variables for each instance of controller in my app?
in view:
<div ng-controller="showProjectList">
{{project_list}}<!--user 1-->
</div>
<div ng-controller="showProjectList">
{{project_list}}<!--user 2-->
</div>
in controller
myapp.controller('showProjectList',function($http)
{ $scope.project_list= <Here I have a http request with argument user_id to fetch project_list>
}
Now how do I initialize each controller with a different user_id? One solution I have readon stackexchange & on google-groups is the use of ng-init.(link google-grp: https://groups.google.com/forum/#!topic/angular/J6DE8evSOBg) .However the use of ng-init is cautioned against in the same threads. So how do you initialize a controller with data then ?
You could use a combination of a controller, a directive and a service for that matter.
The controller is holding the user id's.
The directive is rendering the project list.
The service is responsible for fetching the data from the server. You could implement a cache and/or use $resource in here.
Here is the template code:
<div ng-controller="Projects">
<!-- here you can put an input element with
ng-model="users" to modify the user list on the fly -->
<div ng-repeat="user in users">
<project-list user="user" />
</div>
</div>
The controller:
myapp.controller('Projects', ['$scope', function($scope) {
$scope.users = [1, 2, 3];
}]);
The directive:
myapp.directive('projectList', ['UserService', function(UserService) {
return {
restrict: 'E',
scope: {
user: "="
},
templateUrl: 'project-list.html',
link: function($scope, $element, $attrs) {
UserService.getUserProject($scope.user).then(function(response) {
$scope.userProjects = response;
});
}
};
}]);
The service:
myapp.factory('UserService', ['$http', function($http) {
var getUserProject = function(user) {
var promise = $http.get('users/' + user + '/project');
return promise;
}
return {
getUserProject: getUserProject
}
}]);
Related
So, I'm using a directive which is a form to allow the app user to edit or create users.
When I navigate to users/:id, I'm pulling in a userDetail view which pulls in a directive user-form.
...
<h1>User Detail</h1>
<p>{{ detail.first_name }}</p>
<p>{{ userDetail.last_name }}</p>
<p>{{ userDetail.age }}</p>
<p>{{ userDetail.address }}</p>
<p>{{ userDetail.gender }}</p>
<user-form ctrl="editUser" user-detail="userDetail"></user-form>
This view has a controller which pulls in the userDetail via an ajax call:
userDetail.controller("UserDetailController", ['$http', '$scope', '$routeParams', function($http, $scope, $routeParams) {
function getUser() {
var url = "http://localhost:3000/api/users/" + String($routeParams.id)
$http.get(url).then(function(response) {
$scope.userDetail = response.data;
if (!response.data) {
document.location = '/#!/error'
}
})
}
getUser();
}]);
So I created my directive and its controller is based on the ctrl attribute when I pull in the directive depending on the page I am:
function createUser($scope, $rootScope, $http) {
$scope.submitUser = function(isValid) {
var url = 'http://localhost:3000/api/users'
var data = $scope.user;
var config = 'contenttype';
if (isValid) {
$http.post(url, data, config).then(function(response) {
$scope.users.push(response.data);
});
}
}
}
function editUser($scope, $http, $routeParams) {
setTimeout(function() {
//get $scope.userDetail
//assign $scope.user = $scopeDetail to populate the form with the details to allow editing.
console.log($scope.user);
}, 2000)
}
function userFormDirective() {
return {
scope: { users: '=', userDetail: '=', user: '=' },
name: 'ctrl',
controller: '#',
templateUrl: 'components/userForm/userForm-template.html',
}
}
var app = angular.module('user-management', [
'ngRoute',
'users',
// 'userForm',
'userDetail'
]).directive('userForm', userFormDirective)
.controller('createUser', createUser)
.controller('editUser', editUser);
Here is my userForm template:
<form name="userForm" novalidate ng-submit="submitUser(userForm.$valid)">
<fieldset>
<dl>
<dt><label for="first-name">First Name</label></dt>
<dd><input id="first-name" ng-model="user.first" type="text" required /></dd>
</dl>
<dl>
<dt><label for="last-name">Last Name</label></dt>
<dd><input id="last-name" ng-model="user.last_name" type="text" required/></dd>
</dl>
<dl>
...
So basically, when I go to users/2, it does an AJAX request to get the user details 9Hence, a timeout function). Then, I want the directive's controller to access the models in the view so that I can assign the userDetails that were obtained and assign it to the models in the view, thereby autpopulating it and allowing edits. Not sure if this is a correct way of doing it because I'm rather new to AngularJS.
I am facing a problem with showing a counter value inside a directive.
I am working on an cart application where I have a header directive which is loading only once, when the app loads. I have list of products with 2 links/buttons for adding in wishlist and adding in cart.
Scenario:
When I am adding a product in wishlist, I am getting that product object from my controller and sending it in a service where I am pushing that object in a service wishlist array. Then I am running a loop to to count the number of objects inside the wishlist array and caching it in a service variable (I am not using $rootScope). I am using another service function to return this updated wishlist array count. Inside the directive I am using this service function to get the updated count.
Problem:
The wishlist array count is updating each time I am adding a product inside the wishlist array. But it is not showing the updated value in the view.
See if you want use service then use its reference variable as below
Jsfiddle link
js Code
var app = angular.module('myApp', []);
app.controller('ctrl', function($scope, myservice) {
$scope.data = myservice.data;
$scope.add = function() {
myservice.add('test');
}
});
app.controller('ctrl2', function($scope, myservice) {
$scope.cart = myservice;
});
app.directive('myDir', function() {
return {
restrict: 'EA',
template: '<span>my dir Count {{cart.data.length}}</span>'
}
});
app.directive('myDir1', function(myservice) {
return {
restrict: 'EA',
template: '<span>my dir1 Count {{data.get().length}}</span>',
scope: {},
link: function(scope) {
scope.data = myservice;
}
}
});
app.service('myservice', function() {
this.data = [];
this.add = function(item) {
this.data.push(item);
};
this.get = function() {
return this.data;
};
return this;
});
HTML code
<div ng-app='myApp'>
<div ng-controller='ctrl'>
CTRL
<button ng-click='add()'>
Add to wishlist
</button>
Data :{{data}}
</div>
<hr>
<div ng-controller='ctrl2'>
Count {{cart.data.length}}
<br> Count {{cart.get().length}}
</div>
</div>
This way you can get service data any where in app
I'm fairly new to AngularJS Directives and was wondering how I could implement passing a custom string, which is a url that contains a controller variable, to be used later on by that controller?
Calling Directive
<div ng-controller="MyController">
<my-custom-form after-submit="group/{{insertedId}}" />
</div>
Directive
app.directive('myCustomForm', function() {
return {
templateUrl: 'myCustomForm.html',
link: function(scope, element, attr) {
scope.loadUrl = attr.afterSubmit;
}
}
});
Controller
app.controller('MyController', function($scope, $location, $http) {
$scope.loadUrl = '';
$scope.insertedId = NULL;
$http({
method:'POST',
url:'edit.php',
data:formData
}).success(function(response) {
$scope.insertedId = response.dbInsertedPrimaryId; // used in "after-submit"
$location.path($scope.loadUrl);
});
});
So when $location.path() called it sends me to a url for example:
http://example.com/group/22
The reason for this is so that I can pass a specific/different url each time the directive is used, like so
<div ng-controller="MyController">
<my-custom-form after-submit="user/{{insertedId}}" />
<my-custom-form after-submit="home/{{insertedId}}/something" />
<my-custom-form after-submit="{{insertedId}}/anything" />
</div>
Or maybe there is a better way to do this? I don't know that's why I'm asking. Thanks.
Try with this
app.directive('myCustomForm', function() {
return {
scope: {
afterSubmit = '#',
},
templateUrl: 'myCustomForm.html',
controller: function($scope) {
console.log($scope.afterSubmit);
}
}
});
Notice that the scope variable name is camelCase (stackOverflow), instead the attribute is dash-case (stack-overflow)
This because HTML cannot understand camelCase and javascript cannot understand dash-case
The # for the variable stand for string. You can use:
# for strings
= for variables coming from the controller (ex: after-submit="ctrl.submitUrl")
& for callbacks (ex: on-submit="ctrl.submit()")
You should use controller: instead of link: ... Here the reason: AngularJS : link vs compile vs controller
I want promise to be returned from controller to directive, as I want to change template based on promise received.
LoginController :
(function() {
angular.module('nd')
.controller('LoginController', loginController);
function loginController(
$scope,
modelFactory,
User,
APPLICATION,
REST_URL,
$resource
) {
$scope.user = modelFactory.create('user', User);
$scope.login = login;
function login() {
var resource = $resource(APPLICATION.host + REST_URL.login);
var promise = resource.save($scope.user);
return promise;
}
}
})();
Button Directive :
(function() {
angular.module('nd')
.directive('ndButton', button);
function button() {
return {
restrict: 'E',
scope: {
ndLable: '#',
ndClick: '&'
},
templateUrl: '../components/fields/button/button.template.html',
link: link
};
function link(scope) {
scope.clickButton = function() {
var promise = scope.ndClick();
promise.$promise.then(function(user) {
console.log(user);
});
};
}
}
})();
login.html :
<form ng-submit="login()">
<div class="input-container">
<nd-text-box
ng-model="user.username"
nd-lable="Username"
nd-id="Username"
nd-required="required"></nd-text-box>
<div class="bar"></div>
</div>
<div class="input-container">
<nd-password
ng-model="user.password"
nd-lable="Password"
nd-id="Password"
nd-required="required"></nd-password>
<div class="bar"></div>
</div>
<div class="button-container">
<nd-button nd-lable="Go"></nd-button>
</div>
<div class="footer">Forgot your password?</div>
</form>
button template :
<button ng-click="clickButton()">
<span>{{ndLable}}</span>
</button>
In directive, at scope.ndClick(), it is calling function login() of controller. In controller, I'm getting promise as { $promise: Promise, $resolved: false }.
I'm returning promise back in directive, but in directive I'm getting promise as undefined.
login.html
<div class="button-container">
<nd-button nd-lable="Go" ndClick="login()"></nd-button>
</div>
Bind the $scope.login method to ndClick
I cant tell you why you receive undefined as a return value. I created a fiddle and got the same result. I think it's a scope issue. Maybe some else can explain it. However i would suggest to use a factory or a service to store the user data, so you're able to use it in your whole application. Here is a fiddle which use a factory to share data between several controller and a directive/component: https://jsfiddle.net/trollr/rjuvagb9/
Otherwise you can add an additional two way binding to your directive scope to synchronize the data.
function button() {
return {
restrict: 'E',
scope: {
ndLable: '#',
ndClick: '&',
ndPromise: '='
},
templateUrl: '../components/fields/button/button.template.html',
link: link
};
Template:
<button nd-promise="loginPromise" nd-click"login()">..</button>
Controller:
function login() {
var resource = $resource(APPLICATION.host + REST_URL.login);
$scope.loginPromise = resource.save($scope.user).$promise;
}
I'm trying to create an AngularJS directive that calls a service created using $resource with the value of the attribute in the template and makes the result available in the scope of the element.
I have a very simple service:
services.factory('Concept', ['$resource', function($resource) {
return $resource('http://example/api/:id');
}]);
And a directive:
directives.directive('anConcept', ['Concept', function(Concept) {
return {
scope: {
anConcept: '#'
},
restrict: 'A',
controller: function($scope, $element) {
$scope.results = Concept.get({id: concept});
}
}
}]);
I then try to invoke this in my view:
<div an-concept="1">
{{results}}
</div>
Looking at the network pane in my browser's debugger I can see the requests getting made, but the result isn't being made available in the scope of the element.
I'm sure I'm making a very basic mistake but I can't figure out what it is.
Note that when you're working with a $resource, you're receiving back a promise. Additionally, you may be running into some trouble with the results property of your $scope if the directive's scope is isolated.
angular.module('myApp', ['ngResource'])
.factory('Concept', ['$resource',
function($resource) {
return $resource('https://api.stackexchange.com/2.2/info');
}
])
.directive('anConcept', ['Concept',
function(Concept) {
return {
restrict: 'A',
link: function($scope, $element, $attrs, $controllers) {
Concept.get({
site: $attrs.anConcept
}, function(results) {
$scope.results = results.items[0].total_users;
});
}
};
}
]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-resource.js"></script>
<div ng-app='myApp'>
<div an-concept="stackoverflow">
Total stackoverflow users: {{results}}
</div>
</div>
It's because the result of that get is a promise. You need to do something like:
Concept.get({id: concept}).success(function(data) {
$scope.results = data;
};
EDIT
Sorry I think I made a mistake, $resource works a bit different then $http :
Concept.get({id: concept}, function(data) {
$scope.results = data;
};
If you want to see that value out of directive,I will say that you will not see it as a simple.because your directive is ISOLATED-SCOPE directive.It means your values in that scope will be isolated from parent scope and you will not see that value out of directive(There is a way to get that isolated scope).But if you want to see it in directive,I will say your code is correct code.If response has been accepted,you result will be defined.