How to show buttons with user authentication in AngularJS? - javascript

Currently I am working on my master project. My application is online portfolio management. User can register on app and create profiles. Now i want to give Edit and Delete buttons on the profile view. But just the users who have created the profile are able to see this buttons. For example, if i am a user of app then only i can see the edit and delete buttons on my profile and i can only see the other user's profile.
I am new in AngularJS. It looks easy but still did not work for me. I have a different views of view profile and edit profile. But i have just one controller for both of it.
This is how my view profile code looks like,
HTML
<section data-ng-controller="ProfilesController as profilesCtrl">
<div class="modal-header">
<div>
<h1>{{profile.firstname}} {{profile.lastname}}</h1>
</div>
<div class="pull-right">
<button class="btn-success btn-lg" type="button" data-ng-click="profilesCtrl.modalUpdate('lg', profile)">Edit</button>
<button class="btn-danger btn-lg" type="button" data-ng-click="profilesCtrl.remove(profile)">
<i class="glyphicon glyphicon-trash">
</i>
</button>
</div>
</div>
</section>
Controller
profilesApp.controller('ProfilesController', ['$scope', '$stateParams', '$location', 'Authentication', 'Profiles', '$modal', '$log',
function($scope, $stateParams, $location, Authentication, Profiles, $modal, $log) {
this.authentication = Authentication;
// Find a list of Profiles
this.profiles = Profiles.query();
// open a modal window to view single profile
this.modalview = function(size, selectedProfile) {
var modalInstance = $modal.open({
templateUrl: 'modules/profiles/views/view-profile.client.view.html',
controller: function($scope, $modalInstance, profile) {
$scope.profile = profile;
console.log(profile);
$scope.ok = function() {
$modalInstance.close($scope.profile);
};
},
size: size,
resolve: {
profile: function() {
return selectedProfile;
}
}
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
// open a modal window to update single profile
this.modalUpdate = function(size, selectedProfile) {
var modalInstance = $modal.open({
templateUrl: 'modules/profiles/views/edit-profile.client.view.html',
controller: function($scope, $modalInstance, profile) {
$scope.profile = profile;
$scope.ok = function() {
$modalInstance.close($scope.profile);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
},
size: size
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
// Remove existing Profile
this.remove = function(profile) {
if (profile) {
profile.$remove();
for (var i in this.profiles) {
if (this.profiles[i] === profile) {
this.profiles.splice(i, 1);
}
}
} else {
this.profile.$remove(function() {
$location.path('modules/profiles/views/list-profiles.client.view.html');
});
}
};
// Update existing Profile
this.update = function(updatedProfile) {
var profile = updatedProfile;
profile.$update(function() {}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
}
]);
Please suggest me some way, how can i fix this issue? Any help would appreciated.

you can use a directive like this:
<button access-level="canEdit">Edit</button>
and your directive is bound to accessLevel:
angular.module("app")
.directive('accessLevel', ['AuthService', 'AUTH_EVENTS', function (authService, authEvents) {
return {
restrict: 'A',
link: function ($scope, element, attrs) {
var accessLevel;
attrs.$observe('accessLevel', function (acl) {
if (acl) {
accessLevel = acl;
updateCss();
}
});
$scope.$on("auth-change", function (event, data) {
switch (data) {
case authEvents.logoutSuccess:
case authEvents.loginSuccess:
updateCss();
break;
case authEvents.notAuthorized:
default:
}
});
function updateCss() {
if (accessLevel) {
if (!authService.isAuthorized(accessLevel)) {
switch (element[0].nodeName) {
case "A":
element.hide();
break;
default:
element.attr("disabled", "disabled");
break;
}
} else {
switch (element[0].nodeName) {
case "A":
element.show();
break;
default:
element.removeAttr("disabled");
break;
}
}
}
}
}
}
}]);
this is a little bit more than what you need, but gives you an idea what you can achieve. (and you have to write your auth service etc.)
as example here is a part of my auth service:
angular.module('app')
.factory("AuthService", ["$rootScope", "$http", "AuthSession", "AUTH_EVENTS", function ($rootScope, $http, AuthSession, AUTH_EVENTS) {
AuthSession.load();
$rootScope.$on('$stateChangeStart', function (event, nextState) {
if (nextState.data && nextState.data.accessLevel && !service.isAuthorized(nextState.data.accessLevel)) {
event.preventDefault();
$rootScope.$broadcast('auth-change', AUTH_EVENTS.loginRequired, nextState.name);
}
});
var service = {
login: function (credentials) {
return $http
.post('/api/account/login', credentials)
.success(function (data, status) {
if ((status < 200 || status >= 300) && data.length >= 1) {
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginFailed);
return;
}
AuthSession.create(data.AccessToken, data.User);
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginSuccess);
}).error(function (data, status) {
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginFailed);
});
},
logout: function () {
AuthSession.destroy();
$rootScope.$broadcast("auth-change", AUTH_EVENTS.logoutSuccess);
},
isAuthenticated: function () {
return (AuthSession.token !== null);
},
isAuthorized: function (accessLevel) {
if (!accessLevel) return true;
return (this.isAuthenticated() && AuthSession.user.UserRoles.indexOf(accessLevel) !== -1);
}
}
return service;
}]);
this service retrieves a bearer token from the server and stores it in the authsession service. the user roles are also stored beside of other user information. since the backend is also secured, one who changes the user roles on the client, can't write to the backend. (everything on client side is just for the look and feel of the user)

Two ways :
Once the profile is created, let the isProfileCreated (you need to make one) column in user details table be updated. On angular load, call and check whether is profile created. use ng-show to show (edit and delete button)if it is true.
Or else, if you are going to edit, anyways you need to get the profile details from the table. in that case, let your server send a false if no profile is created or an json object if created.
In your controller use
if(angular.isObject(profile)){
$scope.showeditbutton = true;
$scope.showdeletebutton = true;
}

Related

Why $scope is not working on the view?

I got the next controller:
.controller('LogInController', function(logInFactory, $scope, $location, $state){
$scope.logIn = function() {
$scope.dataLoading = true;
logInFactory.logIn($scope.email, $scope.password, function (response) {
if (response.success) {
$scope.userName = response.userName;
console.log('userName', $scope.userName);
logInFactory.setCredentials($scope.email, $scope.password);
$location.path('/users');
} else {
$scope.dataLoading = false;
}
});
};
$scope.clearCredentials = function(){
$state.go('login');
logInFactory.clearCredentials();
};
});//End controller
I want to use it in this view:
<div class="header" ng-controller = 'LogInController'>
<img src= "logo.jpg">
{{userName}}
<button ng-click = 'clearCredentials()'> Cerrar sesión</button>
</div>
But userName is not showing in the view but when I print it on the controller it is displayed correctly. That view is displayed after call the logIn() function.
This is the logIn function in my factory:
var logIn = function(email, password, callback){
var URL;
if(ENV.mocksEnable){
URL = ENV.apiMock + ENV.logInMock;
return (
$timeout(function () {
var response;
getUser()
.then(function (user) {
console.log('USER', user);
if (user !== null) {
response = { success: true, userName: user.userName};
} else {
response = { success: false, message: 'Username or password is incorrect' };
}
callback(response);
});
}, 1000)
);
}else{
URL = ENV.apiURL + ENV.logIn;
return (
$http.post(URL, {email : email, password : password})
.then(function onFulfilled(response){
var data = response.data;
userName = data.username;
userEmail = data.email;
userId = data.id;
profiles = data.profiles;
callback(response);
return data;
})
.catch(function onRejected(errorResponse){
console.log('Error in logInFactory');
console.log('Status: ', errorResponse.status);
callback(errorResponse);
return errorResponse;
})
);
}
};//End login
I trigger the logIn() function in this view
<form ng-submit = 'logIn()'>
<h1>Log In</h1>
Correo electrónico:
<input type="email" ng-model='email' required><br>
Contraseña
<input type="password" ng-model='password' required><br>
<input type="submit" value="Log in">
</form>
When I tigger logIn() I should go to that header and show the userName.
why are you triggering clearCredentials() ? whereas according to this code you should triggering login() instead.
The result of your logIn() function may be out of Angular scope.
Try wrapping the result of the logIn function into a $timeout (which calls $apply, a way to force Angular to refresh a controller scope):
$timeout(function() {
if (response.success) {
$scope.userName = response.userName;
console.log('userName', $scope.userName);
logInFactory.setCredentials($scope.email, $scope.password);
$location.path('/users');
} else {
$scope.dataLoading = false;
}
});
Do not forget to inject the dependency $timeout in your controller.
You have $scope.userName inside the success of the logIn method. It won't be available until that has happened.
If you put $scope.userName outside of the method and set it to something, it would appear.
.controller('LogInController', function(logInFactory, $scope, $location, $state) {
$scope.userName = 'test name';
$scope.logIn = function() { ...
Something like that.
we don't have your factory code but this line is very strange to me :
logInFactory.logIn($scope.email, $scope.password, function (response) { ..; } )
so your passing the fonction to the factory and it is not the factory who returning data to the controller.
it should be something like this :
logInFactory.logIn($scope.email, $scope.password).then(function (response) { ..; } );
EDIT :
You have to remove the callback function from your factory and make the factory return data and handle data like this logInFactory.logIn($scope.email, $scope.password).then(function (response) { ..; } );.
You have log in the console but the $scope is not shared between the factory and controller so the callback in your factory edit the $scope.userName but the controller cannot get this change.
My problem was that I was expecting to get data from a controller to two different views. And when I go from LogIn view to my header view, the controller refresh its data. So, I have to create in my factory:
var getUserName = function() {
return userName;
};
And in the controller
$scope.userName = logInFactory.getUserName();
Now my userName persists in the factory.

Angular-Formly: Interacting with multiple forms in multiple directives

i'm trying to figure out how to save and react on multiple forms in multiple directives.
To give you a short overview:
Screenshot of the current view
I've got three tabs containing forms and a fourth containing a JsTree (Groups). Each of the three tabs contains a directive, which, in turn, contains a Formly form.
The tabs are wrapped by a main directive which contains a footer directive with the save and cancel buttons in the bottom right corner.
Main directive:
/**
* Displays the ui for editing a specific user
*/
export function UserDetailsDirective() {
class UserDetailsDirective {
/*#ngInject*/
constructor(
$stateParams,
userService,
formlyChangeService
) {
this.currentUser = this.currentUser || {};
this.originalUser = this.originalUser || {};
this.userForms = {
mainData: {},
personalData: {},
basicSettings: {}
};
this.savingAllowed = true;
/* Second try: Registering a callback at the change service, which will be executed on any field change in the passed form (mainData) */
formlyChangeService.onFormChange('mainData', () => {
console.log('test123');
console.log('this123', this);
console.log('this.userForms.mainData.api.isValid()', this.userForms.mainData.api.isValid());
});
if ($stateParams.id > 0) {
userService.getUser($stateParams.id).then((userData) => {
userData.Birthday = new Date(userData.Birthday);
this.currentUser = userData;
this.breadcrumbData = [...];
})
}
}
onSave(controller) {
alert('on save');
console.log('controller', controller);
}
}
return {
restrict: 'E',
templateUrl: 'components/usermanagement/edit/user-details/user-details.directive.html',
controller: UserDetailsDirective,
controllerAs: 'controller',
bindToController: true
}
}
<breadcrumb [...]></breadcrumb>
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" data-target="#mainData">Account data</a></li>
<li><a data-toggle="tab" data-target="#personalData">Personal data</a></li>
<li><a data-toggle="tab" data-target="#basicSettings">Settings</a></li>
<li><a data-toggle="tab" data-target="#userGroupAssignment">Groups</a></li>
</ul>
<div class="row">
<div class="col-lg-6">
<div class="tab-content">
<div id="mainData" class="tab-pane fade in active">
<main-data user="controller.currentUser"></main-data>
</div>
<div id="personalData" class="tab-pane fade">
<personal-data user="controller.currentUser"></personal-data>
</div>
<div id="basicSettings" class="tab-pane fade">
<basic-settings user="controller.currentUser"></basic-settings>
</div>
<div id="userGroupAssignment" class="tab-pane fade">
<group-assignment user="controller.currentUser"></group-assignment>
</div>
</div>
</div>
<div class="col-lg-6">
[...] <!-- Right column -->
</div>
</div>
<!-- Footer -->
<user-details-footer
on-save="controller.onSave(controller)"
saving-allowed="controller.savingAllowed"
></user-details-footer>
Footer directive
/**
* Displays the user details footer
*/
export function UserDetailsFooterDirective() {
class UserDetailsFooterDirective {
/*#ngInject*/
constructor(
$state,
Notification,
$translate
) {
this.state = $state;
this.notification = Notification;
this.translate = $translate;
this.savingAllowed = this.savingAllowed || false;
}
/**
* Event that is triggered on save button click
*
* Propagates to the parent controller via attribute binding
*/
saveEvent() {
if (typeof this.onSave === 'function') {
this.onSave();
}
}
/**
* Navigates to the user list
*/
goToUserList() {
this.state.go('userList');
}
}
return {
restrict: 'E',
templateUrl: 'components/usermanagement/edit/user-details-footer/user-details-footer.directive.html',
controller: UserDetailsFooterDirective,
controllerAs: 'controller',
bindToController: true,
scope: {
onSave: '&?',
savingAllowed: '=?'
}
}
}
<nav class="navbar navbar-fixed-bottom">
<div class="container-fluid pull-right">
<button class="btn btn-default" ng-click="controller.goToUserList()"><i class="fontIcon fontIconX"></i> Cancel</button>
<button class="btn btn-primary" ng-disabled="controller.savingAllowed !== true" ng-click="controller.saveEvent()"><i class="fontIcon fontIconSave"></i> Save</button>
</div>
</nav>
First tab's directive
/**
* Displays the contents of the tab "Account data"
*/
export function MainDataDirective() {
class MainDataDirective {
/*#ngInject*/
constructor(
formlyFormService,
mainDataFieldProviders,
$state,
userSubmitService,
$timeout,
formlyChangeService,
$scope
) {
this.state = $state;
this.$timeout = $timeout;
this.userSubmitService = userSubmitService;
this.model = {};
this.originalUser = this.originalUser || {};
this.fields = [];
this.form = null;
var that = this;
/* Third try: Watching the form instance => partial success */
this.watch('formMainData', function(x, y, form) {
console.log('formMainData', form);
that.form = form;
form.watch('$invalid', function(foo, bar, value) {
/* This will react on field changes but it seems really dirty to me */
console.log('$invalid', arguments);
});
});
formlyFormService.getFormConfiguration(mainDataFieldProviders).then((result) => {
/* Here the formly fields are set */
this.fields = result;
/* Second try: A service which provides a callback that will be executed on field invalidation => no success */
formlyChangeService.registerFields(this.fields, 'mainData');
}, (error) => {
console.error('getMainDataFields error:', error);
});
this.api = {
isValid: angular.bind(this, this.isValid),
submit: angular.bind(this, this.onSubmit)
}
}
/* First try to get the validity of the fields => no success */
isValid() {
//return this.$timeout(() => {
let isValid = true;
this.fields.some((field) => {
if (
field.validation.errorExistsAndShouldBeVisible === true
|| field.validation.serverMessages.length > 0
) {
isValid = false;
return true;
}
});
//return isValid;
//}, 10);
return isValid;
}
/**
* Method triggered by the formSubmit event
*/
onSubmit() {
this.userSubmitService.submitUser(this.fields, this.model);
}
}
return {
restrict: 'E',
templateUrl: 'components/usermanagement/edit/main-data/main-data.directive.html',
controller: MainDataDirective,
controllerAs: 'controller',
bindToController: true,
scope: {
originalUser: '=user',
api: '=?'
},
link: (scope) => {
scope.$watch('controller.originalUser', (newValue) => {
if (newValue.hasOwnProperty('ID')) {
scope.controller.model = angular.copy(newValue);
}
});
}
}
}
<form name="controller.form" ng-submit="controller.onSubmit()" class="form-horizontal" novalidate>
<formly-form form="controller.formMainData" model="controller.model" fields="controller.fields" ></formly-form>
</form>
Second try: FormlyChangeService => got change event fired but before validation => no success
export /*#ngInject*/ function FormlyChangeService() {
let callbacks = [];
return {
triggerFormChangeEvent: triggerFormChangeEvent,
registerFields: registerFields,
onFormChange: onFormChange
};
function triggerFormChangeEvent(value, options) {
callbacks.forEach((callback) => {
if (
typeof callback === 'function'
&& callback.formDirective === options.templateOptions.formDirective
) {
callback();
}
});
}
function onFormChange(formDirective, callback) {
callback.formDirective = formDirective;
callbacks.push(callback);
}
function registerField(fieldConfig) {
fieldConfig.templateOptions.changeEvents.push(
triggerFormChangeEvent
);
}
function registerFields(fieldConfigs, formDirective) {
fieldConfigs.forEach((fieldConfig) => {
fieldConfig.templateOptions.formDirective = formDirective;
registerField(fieldConfig);
fieldConfig.watcher = {
listener: function() {
console.log('listener', arguments);
}
};
console.log('fieldConfig', fieldConfig);
fieldConfig.watch('$valid', function() {
console.log('valid field', arguments);
});
});
}
}
The Formly forms are fed with an user model, which is provided by the main directive.
I have to save all four tabs at the same time because there are several mandatory fields that have to be present to save the entered record.
Now here comes the tricky part:
I want the save button to be disabled if the model hasn't changed or an error occurred at any field in any form. I also want to know which form the error comes from.
What i thought about is an event or watcher in the Formly field config or something similar.
I've tried the onChange event on the field config but it is fired right before the field validation runs, so i won't get the current error status of that field.
The error status has to be passed up to the main directive from where it should be passed down to the save button.
Can anyone help me getting the forms (or even better the respective fields) to tell the main directive that there is an invalid field?
It's really difficult to exemplify such a complex task, so if there is any obscurity please let me know.
Thank you very much in advance.
Julian
I think you should have a service or factory that all your directive depend on that holds the data for all your forms.
This way you can set up a watch in your directive that will call whatever method on your shared service to validate / invalidate forms on your other tabs.
I hope this helps

ng-show - using a service as a scope parameter

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;
};
});

Call 2 functions in single ng-click

I am calling two functions on ng-click. But it doesn't work. I am not sure why the Refresh1() is not called when I cross-checked through debugger.
HTML CODE
<div class="row" ng-controller="PublishManifestCtrl">
<div class="col-xs-12 col-md-12">
<div class="widget">
<div class="widget-header bordered-bottom bordered-themeprimary">
<i class="widget-icon fa fa-tasks themeprimary"></i>
<span class="widget-caption themeprimary">Manifest Status</span>
</div>
<div class="widget-body">
<form class="form-bordered" role="form">
<div class="form-group">
<label style="padding-left: 8px;">Manifest was last published to agents on <b>{{manifeststatus.manifestLastPublishedDate}}</b>.</label>
</div>
<div class="form-group">
<label style="padding-left: 8px;">Manifest was last updated by <b> {{manifeststatus.lastUpdatedByUser}} </b> on <b>{{manifeststatus.manifestLastedUpdatedDate}}</b>.</label>
</div>
<div class="form-group">
<div class="col-sm-offset-1">
**<button id="PublishButton" class="btn btn-default shiny " ng-disabled="manifeststatus.enablePublishButton" ng-click="Save(manifeststatus);Refresh1()">Publish</button>**
</div>
<br/>
<div id="statusDivPublish" ng-show="showstatus">
<alert type="{{alert.type}}">{{alert.msg}}</alert>
</div>
</div>
</form>
</div>
JSFILE
$scope.Save = function (data) {
debugger;
$http.post($rootScope.WebApiURL + '/updatemanifeststatus');
//$http.get({ url: $rootScope.WebApiURL + '/getmanifeststatus' });
$scope.manifeststatus = data;
$scope.showstatus = true;
$scope.alert = { type: 'success', msg: 'Published Successfully.' };
$(".statusDivPublish").show();
}
$scope.Refresh1 = function () {
//refresh
$state.transitionTo($state.current, $stateParams, {
reload: true,
inherit: false,
notify: true
});
}
});
new code
$scope.Save = function (data) {
debugger;
$http.post($rootScope.WebApiURL + '/updatemanifeststatus');
//$http.get({ url: $rootScope.WebApiURL + '/getmanifeststatus' });
$scope.manifeststatus = data;
$scope.showstatus = true;
$scope.alert = { type: 'success', msg: 'Published Successfully.' };
$(".statusDivPublish").show();
$scope.Refresh1();
}
$scope.Refresh1 = function ($rootScope, $state, $stateParams) {
debugger;
return {
restrict: 'AC',
link: function (scope, el, attr) {
el.on('click', function () {
$state.transitionTo($state.current, $stateParams, {
reload: true,
inherit: false,
notify: true
});
});
}
};
};
});
The first one updates and displays a successfull message, while the second function refreshes the page.
use this
$scope.Save = function (data) {
debugger;
$http.post($rootScope.WebApiURL + '/updatemanifeststatus');
//$http.get({ url: $rootScope.WebApiURL + '/getmanifeststatus' });
$scope.manifeststatus = data;
$scope.showstatus = true;
$scope.alert = { type: 'success', msg: 'Published Successfully.' };
$(".statusDivPublish").show();
$scope.refresh();
}
call refresh inside the first function and remove it from the ng-click.
Update
You have a different type of problem i had it too. you try to refresh a state inside a method, it's really difficult i solve that problem with this snippet
if($state.current.name == /*name of the current state*/) {
$state.go($state.current, {}, {reload: true});
$modalInstance.close();
}
else {
$modalInstance.close();
$state.go(/*name of the current state*/);
}
it's not difficult but it didn't behave like you have understand it.
UPDATE
taking your code
$scope.Refresh1 = function () {
//refresh
$state.go($state.current, {}, {reload: true});
}
What about calling refresh inside of save in $http handler ?
Like this:
$http.post($rootScope.WebApiURL + '/updatemanifeststatus')
.then(function(){
$scope.Refresh1();
});
Don't execute two function in one ng-click, instead add the Refresh1 call to the end of the Save call, like so.
HTML
<button id="PublishButton"
class="btn btn-default shiny "
ng-disabled="manifeststatus.enablePublishButton"
ng-click="Save(manifeststatus)">Publish</button>
JS
$scope.Save = function (data) {
debugger;
$http.post($rootScope.WebApiURL + '/updatemanifeststatus');
//$http.get({ url: $rootScope.WebApiURL + '/getmanifeststatus' });
$scope.manifeststatus = data;
$scope.showstatus = true;
$scope.alert = { type: 'success', msg: 'Published Successfully.' };
$(".statusDivPublish").show();
$scope.refresh();
}
Update
If you are using AngularJS V1.2.2 or higher, then using ui-router, the following should work to reload the data.
$state.transitionTo($state.current, $stateParams, {
reload: true,
inherit: false,
notify: true
});
The shortest way to accomplish this though would be with:
$state.go($state.current, {}, {reload: true}); //second parameter is for $stateParams
Its also worth noting that none of these will actually reload the page. If you want to reload the state AND the page, there is no ui-routermethod for it. Do window.location.reload(true)
Update 2
If you are receiving:
$state is not defined at Scope.$scope.Refresh1
(publishmanifest.js:44) at Scope.$scope.Save (publishmanifest.js:37)
at $parseFunctionCall (angular.js:12345) at angular-touch.js:472 at
Scope.$eval (angular.js:14401) at Scope.$apply (angular.js:14500) at
HTMLButtonElement. (angular-touch.js:471) at
HTMLButtonElement.n.event.dispatch (jquery.min.js:3) at
HTMLButtonElement.r.handle (jquery.min.js:3)
You are not injecting the $state service in your controller. You must do this in order to use it.
//without annotation (inferred, not safe when minifying code)
function Controller($scope, $state) {...}
//inline annotation
module.controller('Controller', ['$scope','$state', function($scope, $state) {...}]);
//$inject property annotation
function Controller($scope, $state) {...}
Controller.$inject = ['$scope', '$state'];
Pick one of the methods above to setup your controller to use $state.
Just make a third function like:
function3(data) {
save(data);
refresh1();
}

scope undefined in Link function in Angular

I have been dealing with this problem for a while. Suppose I have the following directive and controller:
angular.module('LiveAPP.artist',[])
.controller('artistCtrl', ['$scope', '$http', '$location', 'dataFactory', '$routeParams', artistCtrl])
.directive("ratestar", function() {
return {
restrict: "E",
template: "<div id='rateYo'></div>",
link: function( scope, ele, attrs ) {
console.log(scope.ratingInfo)
if(scope.reviews === undefined){
$rateYoMain = $(ele).rateYo({
rating:3
})
} else {
var $rateYo = $(ele).rateYo({
starWidth: "20px",
rating:scope.review.number_of_stars
});
}
}
};
})
function artistCtrl($scope, $http, $location, dataFactory, $routeParams){
$scope.artistName = $routeParams.artistname;
$scope.$watch( 'artistName', function( newValue, oldValue ) {
dataFactory.checkDb( newValue ).then(function(dbData){
if(dbData.data != "No data"){
$scope.artistInfo = dbData.data[0];
$scope.reviews = dbData.data[1];
$scope.ratingInfo = dataFactory.avgReview($scope.reviews);
} else{
dataFactory.artistInfoAPIs(newValue);
}
})
});
$scope.$on('artist:updated', function(event, data){
$scope.artistInfo = data;
});
$scope.ratingInfo = "12";
$scope.artistInfo = {
artist_name: dataFactory.artistInfo.artist_name,
artist_genre: dataFactory.artistInfo.artist_genre,
artist_imageurl: dataFactory.artistInfo.artist_imageurl,
artist_bio: dataFactory.artistInfo.artist_bio
};
}
The associated view is the following:
<div class="mainstar"><ratestar></ratestar></div>
<div class='reviews' ng-repeat="review in reviews">
<ratestar class="reviewstars"></ratestar>
</div>
I having an issue with the scope in the link function. When artistName changes there is a GET request that is sent to the database, which then responds with the correct data. The data that I am concerned about is what gets assigned to $scope.ratingInfo in the promise callback. The weird thing is that this data is 12 when I console.log(scope.ratingInfo) in the link function only for <div class="mainstar"><ratestar></ratestar></div> but not for the <ratestar></ratestar> s in the ng-repeat. Getting '12' makes sense since that is how I define it when the controller is instantiated. Ideally I would like to see the data in the same way that I am seeing it when it comes to <ratestar></ratestar> s in the ng-repeat. I can't seem to figure this out. Anyone have any idea whats going on here?
Could you try this ?
<div class="mainstar"><ratestar ratingInfo="ratingInfo" review="review"></ratestar></div>
<div class='reviews' ng-repeat="review in reviews">
<ratestar class="reviewstars" ratingInfo="ratingInfo" review="review"></ratestar>
</div>
.directive("ratestar", function() {
return {
restrict: "E",
template: "<div id='rateYo'></div>",
scope: {
ratingInfo : '=ratingInfo',
review: '=review'
},
link: function( scope, ele, attrs ) {
console.log(scope.ratingInfo)
if(scope.reviews === undefined){
$rateYoMain = $(ele).rateYo({
rating:3
})
} else {
var $rateYo = $(ele).rateYo({
starWidth: "20px",
rating:scope.review.number_of_stars
});
}
}
};
});

Categories