Accessing parent $scope - angularjs

I have posted earlier this post with the choice of not providing all my code. But now im stuck since with the same problem so I give it a change with providing all my code.
I know its not easy to debug when the code is huge so I will try to explain precisely the problem.
Actually the problem is described in my precedent post so please read it and look at the code that is a simplification of this one.
But basically the problem is : I want to access $scope.data.comments from the $scope.deleteComment() function
As you see the code below you will notice that I have to add ng-controller="CommentController" twice for this to work.
If someone could explain why.. that would be great but I guess that is another question.
Thanks in advance for your help.
MAIN HTML
<div ng-init="loadComments('${params.username}', '${params.urlname}' )" ng-controller="CommentController">
<div ng-repeat="comments in data.comments" >
<div sdcomment param="comments" ></div>
</div>
</div>
APP
var soundshareApp = angular.module('soundshareApp', ['ngCookies']);
DIRECTIVES
soundshareApp.directive('sdcomment', ['$cookies', function($cookies){
var discussionId = null;
var found = false;
var username = $cookies.soundshare_username;
return {
restrict:'A',
scope: {
commentData: '=param'
},
templateUrl: '/js/views/comment/templates/commentList.html',
link : function(scope, element, attrs, controller) {
scope.$watch(element.children(), function(){
var children = element.children();
for(var i=0; i<children.length; i++){
if(children[i].nodeType !== 8){ //pas un commentaire <!-- -->
if( !found ){
found = true;
discussionId == scope.commentData.discussionId
}else if(found && discussionId == scope.commentData.discussionId){
angular.element(children[i]).removeClass('message-content');
angular.element(children[i]).addClass('answer-message-content');
}
if(found && discussionId != scope.commentData.discussionId){
discussionId = scope.commentData.discussionId
}
if(username == scope.commentData.username){
element.parent().bind('mouseover', function() {
// $(".delete-comment-button").show()
element.parent().find("span.delete-comment-button:first").attr('style', 'display: block !important');
});
element.parent().bind('mouseleave', function() {
element.parent().find("span.delete-comment-button:first").attr('style', 'none: block !important');
});
}
}
}
});
}
}
}]);
TEMPLATE
<div class="message-wrapper" ng-controller="CommentController">
<div class='message-content' ng-click="state.show = !state.show; setUsername(commentData.username)">
<img class='message-vignette' ng-src='{{commentData.avatarUrl}}'/>
<div class='message-username'>{{commentData.username}}</div>
<div class='project-message'>{{commentData.comment}}</div>
<div class='message-date'>{{commentData.dateCreated | date:'dd.MM.yyyy # hh:mm:ss' }}</div>
<div class="clearfix"></div>
</div>
<div ng-repeat="answer in answers" class="answer-message-content" >
<div class='message-content' ng-click="state.show = !state.show">
<img class='message-vignette' ng-src='{{answer.avatarUrl}}'/>
<div class='message-username'>{{answer.username}}</div>
<div class='project-message'> {{answer.comment}}</div>
<div class='message-date'>{{answer.dateCreated | date:'MM/dd/yyyy # h:mma' }}</div>
<div class="clearfix"></div>
</div>
</div>
<div class="add-comment-content show-hide" ng-show="state.show" >
<img class='message-vignette answer-message-vignette' ng-src='{{commentData.currentUserAvatarUrl}}'>
<div class="">
<form ng-submit="addComment(commentData)" id="commentForm-{{commentData.projectId}}">
<input id="input-comment-{{commentData.projectId}}" type="text" maxlength="" autofocus="autofocus" name="comment" placeholder="Write a comment..." ng-model="commentData.msg">
<input type="hidden" name="discussionId" value="{{commentData.discussionId}}" >
<input type="hidden" name="projectId" value="{{commentData.projectId}}" >
</form>
</div>
</div>
<span ng-click="deleteComment(commentData)" class="btn btn-default btn-xs delete-comment-button"><i class="icon-trash"></i></span>
</div>
CONTROLLER
'use strict';
soundshareApp.controller('CommentController', function($scope, $http) {
$scope.data = { comments : [] }
$scope.answers = [];
$scope.state = {}
$scope.project = { id : [] }
$scope.username = null;
$scope.loadComments = function(userName, urlName){
$http({
url: '/comment/by_project_id',
method: "GET",
params:
{
username: userName,
urlname: urlName
}
}).success(function(data) {
$scope.data.comments = data;
console.log($scope.data.comments);//WORKING
});;
}
$scope.addComment = function(commentData){
if("undefined" != commentData.msg){
commentData.msg = "#" + $scope.username + ": " + commentData.msg;
$http({
method : "POST",
url : "/comment/addAnswer",
params:
{
comment: commentData.msg,
discussionId: commentData.discussionId,
projectId:commentData.projectId
}
}).success(function(data){
$scope.answers.push(data);
$('.show-hide').hide();
$scope.commentData.msg = '';
});
}
}
$scope.setUsername = function(username){
$scope.username = username;
}
$scope.deleteComment = function ( comment ) {
console.log($scope.data.comments);//NOT WORKING
};
});

Related

AngularJS multi screen validation on last step

I have an angularJS application. I have implemented a generic workflow using $routeProvider, templateUrl & Controllers.
Each step(screen) is verified when user click on next button and moves to the next step if validation passes. If validation fails user is required to fix all the error, displayed on the screen, before moving to next step.
When user has visited all the screens(passed validation for each screen) all the breadcrumbs get enabled and now user can move freely between those steps/breadcrumbs.
Requirement:
Now I want to allow user to move freely between steps by clicking on the breadcrumbs and when user clicks on the lodge button, on the last step, validation for current as well as for all previous steps should be invoked, and clicking on the error user should be able taken to the relevant step/screen.
Also I want to keep the functionality of validating the individual steps on the click of next button.
As you can see each screen has a separate controller along with the scope.
Once user move from one step to another it can't access the previous scope.
Initially I thought of storing scope of each screen in an array, but once I move between steps new scope is created (as it should) and only current step has a form with valid data model and "valid" flag as false.
Form object at current step
Form object of other screen without and fields attached
I'm not very well versed with Angularjs and trying to get some idea weather
Is it possible what I'm trying to achieve keeping the existing functionality intact. (My understanding is that I can't have a single controller since I need to keep the functionality of validating each step individually)?
Is there a better way to trying to achieve this functionality?
PS: Sadly I can't upgrade to newer version of Angular.
Any help will be highly appreciated.
Form Validation
validator.validate = function($scope, submitCallback, additionalOptions) {
var options = {};
$.extend(options, commonOptions, additionalOptions);
var form = $scope[options.formName];
hideErrorMessages(options.errorContainerSelectorId);
if (form.$valid) {
submitCallback();
return;
}
showErrorMessages({message: composeAngularValidationErrors(form),
errorContainer: $('#' + options.errorContainerSelectorId)});
};
View:
<#assign temp=JspTaglibs["http://www.test.com/tags"]>
<div ng-controller="LodgeApplicationWorkflowController" ng-cloak>
<workflow-breadcrumbs></workflow-breadcrumbs>
{{model | json}}
<div ng-view>
</div>
<script type="text/ng-template" id="applicant-details">
<form name="form" method="post" action="#" class="standard">
<h3>Primary contact details</h3>
<div class="row">
<div class="span3">
<label for="owner-primary-contact">Primary contact:</label>
<select class="span3" id="owner-primary-contact" required name="applicantDetails.primaryContact"
ng-model="model.applicantDetails.primaryContactId"
ng-options="user.id as user.fullName for user in refData.contactInfos"
>
<option value=""></option>
</select>
</div>
<div class="span3">
<label for="owner-primary-contact-phone">Phone:</label>
<input type="text" class="span3" id="owner-primary-contact-phone" name="applicantDetails.primaryContactPhone"
readonly
ng-model="model.applicantDetails.primaryContactPhone"/>
</div>
<div class="span3">
<label for="owner-primary-contact-email">Email:</label>
<input type="text" class="span3" id="owner-primary-contact-email" name="applicantDetails.primaryContactEmail"
readonly
ng-model="model.applicantDetails.primaryContactEmail"/>
</div>
</div>
</form>
</script>
<script type="text/ng-template" id="lgc-methodology">
<form name="form" method="post" action="#" class="standard">
<h3>Describe the Your Methodology</h3>
<div class="row">
<div class="span9">
<label for="methodology">Describe the methodology which you propose to employ:
</label>
<textarea class="span9" id="methodology" name="methodology"
rows="10"
ng-maxlength="4000"
ng-model="model.methodology" required>
</textarea>
</div>
</div>
</form>
</script>
<script type="text/ng-template" id="approval-details">
<form name="form" method="post" action="#" class="standard">
<div class="row" ng-if="model.approvalDetails.planningApprovalsObtained === 'true'">
<div class="span9">
<label for="planning-approvals-details">Approval details:</label>
<textarea class="span6" id="planning-approvals-details"
name="approvalDetails.planningApprovalDetails"
ng-if="model.approvalDetails.planningApprovalsObtained === 'true'"
required ng-maxlength="4000"
ng-model="model.approvalDetails.planningApprovalDetails"></textarea>
</div>
</div>
<div class="row" ng-if="model.approvalDetails.planningApprovalsObtained === 'false'">
<div class="span9">
<label for="planning-approvals-details">Reasons:</label>
<textarea class="span6" id="planning-approvals-details"
name="approvalDetails.planningApprovalDetails"
ng-if="model.approvalDetails.planningApprovalsObtained === 'false'"
required ng-maxlength="4000"
ng-model="model.approvalDetails.planningApprovalDetails"></textarea>
</div>
</div>
<div >
<div class="row" >
<div class="span9">
<label for="environment-approval-details">Approval details:</label>
<textarea class="span6" id="environment-approval-details"
name="approvalDetails.environmentApprovalDetails"
ng-maxlength="4000"
ng-required="model.approvalDetails.environmentApprovalsObtained === 'true'"
ng-model="model.approvalDetails.environmentApprovalDetails"></textarea>
</div>
</div>
<div class="row" ng-if="model.approvalDetails.environmentApprovalsObtained === 'false'">
<div class="span9">
<label for="environment-approval-details">Reasons:</label>
<textarea class="span6" id="environment-approval-details"
name="approvalDetails.environmentApprovalDetails"
ng-maxlength="4000"
ng-required="model.approvalDetails.environmentApprovalsObtained === 'false'"
ng-model="model.approvalDetails.environmentApprovalDetails"></textarea>
</div>
</div>
</div>
</form>
</script>
<script type="text/ng-template" id="confirmation">
<form id="form" method="post" name="form" action="#" class="standard">
<div class="row">
<div class="span9">
<span class="checkbox inline">
<label for="confirm-information">
<input type="checkbox" id="confirm-information" name="confirmInformation"
ng-model="model.Confirmed" required />
I confirm that all the details are correct
</label>
</span>
</div>
</div>
</form>
</script>
<div class="form-actions">
<input type="button" class="btn" value="Cancel" ng-click="cancel()"/>
<div class="pull-right btn-toolbar">
<input id="previous" type="button" class="btn" value="Previous"
ng-click="workflow.handlePrevious()" ng-show="!workflow.isFirstStep()" ng-cloak/>
<input id="save-and-close" type="button" class="btn" value="Save draft and close"
ng-show="model.canSaveDraftAndClose && !workflow.isLastStep()"
ng-click="saveDraftAndClose()" ng-cloak/>
<input id="submit" type="button" class="btn btn-primary" value="{{workflow.getNextLabel()}}"
ng-disabled="!workflow.canNavigateToNextStep()"
ng-click="workflow.handleNext()" ng-cloak/>
</div>
</div>
</div>
Controllers:
angular.module('Test')
.config(function ($routeProvider) {
$routeProvider
.when('/applicant-details', {
templateUrl: 'applicant-details',
controller: 'ApplicantDetailsController'
})
.when('/methodology', {
templateUrl: 'methodology',
controller: 'MethodologyController'
})
.when('/approval-details', {
templateUrl: 'approval-details',
controller: 'ApprovalDetailsController'
})
.when('/confirmation', {
templateUrl: 'confirmation',
controller: 'ConfirmationController'
})
.otherwise({redirectTo: '/applicant-details'});
})
;
function LodgeApplicationWorkflowController( $scope, ctx, workflow, workflowModel, server, navigation) {
workflow.setSteps([
{
name: 'Applicant details',
path: 'applicant-details',
validationUrl: '/some url'
},
{
name: 'Methodology',
path: 'methodology'
},
{
name: 'Approval details',
path: 'approval-details'
},
{
name: 'Confirmation',
path: 'confirmation',
nextButtonLabel: 'Lodge',
onSubmit: function () {
disable('submit');
$scope.model.lodgeApplication = JSON.stringify($scope.model);
server.post({
url: ctx + '/some url' ,
json: JSON.stringify($scope.model),
successHandler: function () {
},
completeHandler: function () {
enable('submit');
},
validationErrorTitle: 'The request could not be completed because of the following issues:'
});
}
}
]);
function postInit() {
// To DO
}
function loadLodgement() {
// To DO
}
$scope.workflow = workflow;
$scope.model = workflowModel.model();
$scope.refData = workflowModel.refData();
$scope.accountDetails = {};
$scope.userDetails = {};
$scope.model.canSaveDraftAndClose = true;
server.getReferenceData([
'/URL1'
], function onAllReferenceDataRetrieved(data) {
$scope.$apply(function() {
$scope.refData.fuelSourceOptions = data[0];
$scope.refData.contactInfos = data[1].result;
$scope.refData.address = data[2];
$scope.refData.yearOptions = data[3];
$scope.refData.nmiNetworkOptions = data[4];
});
loadLodgement();
loadDraft();
});
$scope.saveDraftAndClose = function () {
var command = {};
server.post({
url: ctx + '/URL',
json: JSON.stringify(command),
successHandler: function (data) {
},
validationErrorTitle: 'The request could not be completed because of the following issues:'
});
};
$scope.cancel = function() {
navigation.to('Some URL');
};
}
function ApplicantDetailsController($scope, workflow, workflowModel, addressService, applicantServiceFactory) {
var applicantService = applicantServiceFactory();
if (!workflow.setCurrentScope($scope)) {
return;
}
$scope.model = workflowModel.model();
$scope.model.applicantDetails = _.extend({
owner: { address: {} },
operator: { address: {} }
}, $scope.model.applicantDetails);
addressService.initialiseAddress($scope.model.applicantDetails);
}
function MethodologyController($scope, workflow, workflowModel) {
if (!workflow.setCurrentScope($scope)) {
return;
}
$scope.model = workflowModel.model();
// Do something
}
function ApprovalDetailsController($scope, workflow, workflowModel) {
if (!workflow.setCurrentScope($scope)) {
return;
}
$scope.model = workflowModel.model();
$scope.model.approvalDetails = $scope.model.approvalDetails || {};
// Do something
}
function ConfirmationController($scope, workflow, workflowModel) {
if (!workflow.setCurrentScope($scope)) {
return;
}
$scope.model = workflowModel.model();
$scope.model.confirmation = { owner: {}, operator: {} };
$scope.model.confirmationConfirmed = false;
// Do something
}
WorkFlow
angular.module('Test')
.service('workflowModel', function() {
var refData = {};
var workflowModel = {};
return {
reset: function() {
workflowModel = {};
},
get : function(fragmentName) {
if (!workflowModel[fragmentName]) {
workflowModel[fragmentName] = {};
}
return workflowModel[fragmentName];
},
model : function(newWorkflowModel) {
if (newWorkflowModel) {
workflowModel = newWorkflowModel;
} else {
return workflowModel;
}
},
refData : function() {
return refData;
},
toJSON: function() {
return JSON.stringify(workflowModel);
}
};
})
.directive('workflowBreadcrumbs', function() {
return {
restrict: 'E',
template: '<ul class="breadcrumb">' +
'<li ng-class="{\'active\': workflow.currentStepPathIs(\'{{step.path}}\')}" ng-repeat="step in workflow.configuredSteps" ng-cloak>' +
'{{step.name}}<span ng-if="!workflow.visitedStep(step.path)">{{step.name}}</span><span class="divider" ng-if="!$last">/</span>' +
'</li>' +
'</ul>',
transclude: true
};
})
.factory('workflow', function ($rootScope, $location, server, validator, workflowModel, $timeout) {
function getStepByPath(configuredSteps, stepPath) {
return _.find(configuredSteps, function(step) { return step.path === stepPath; });
}
function validateServerSide(currentStep, callback) {
if (currentStep.validationUrl) {
server.post({
url: ctx + currentStep.validationUrl,
json : JSON.stringify(workflowModel.model()),
successHandler : function() {
$rootScope.$apply(function() {
callback();
});
}
});
} else {
callback();
}
}
function navigateNext(configuredSteps, currentStep) {
var currentStepIndex = _.indexOf(configuredSteps, currentStep);
navigateTo(configuredSteps[currentStepIndex + 1]);
}
function navigateTo(step) {
$location.path(step.path);
}
return {
setCurrentScope: function(scope) {
this.currentScope = scope;
this.firstStep = _.first(this.configuredSteps);
this.lastStep = _.last(this.configuredSteps);
this.currentStep = this.getCurrentStep();
if (!(this.currentStep === this.firstStep || this.hasEverVisitedSteps())) {
this.reset();
return false;
}
this.currentStep.visited = true;
hideErrorMessages();
this.focusOnFirstInputElementAndScrollToTop();
return true;
},
setSteps: function(steps) {
this.configuredSteps = steps;
},
focusOnFirstInputElementAndScrollToTop: function() {
$timeout(function() {
angular.element('select, input, textarea, button', '[ng-view]')
.filter(':visible')
.first()
.one('focus', scrollToTitle)
.focus();
scrollToTitle();
});
},
hasEverVisitedSteps: function() {
return _.find(this.configuredSteps, function(step) {
return step.visited;
}) !== undefined;
},
isFirstStep: function() {
return this.currentStep === this.firstStep;
},
isLastStep: function() {
return this.currentStep === this.lastStep;
},
currentStepPathIs: function(stepPath) {
return this.currentStep && stepPath === this.currentStep.path;
},
visitedStep: function(stepPath) {
return getStepByPath(this.configuredSteps, stepPath).visited;
},
getNextLabel: function() {
if (this.currentStep && this.currentStep.nextButtonLabel) {
return this.currentStep.nextButtonLabel;
}
return (this.isLastStep()) ? 'Submit' : 'Next';
},
handlePrevious: function() {
if (!this.isFirstStep()) {
var currentStepIndex = _.indexOf(this.configuredSteps, this.currentStep);
navigateTo(this.configuredSteps[currentStepIndex - 1]);
}
},
canNavigateToNextStep: function() {
return this.currentScope && (!this.currentScope.canSubmit || this.currentScope.canSubmit());
},
handleNext: function() {
var configuredSteps = this.configuredSteps;
var currentStep = this.currentStep;
if(this.isLastStep()) {
this.validateCurrentStep(this.currentStep.onSubmit);
} else {
this.validateCurrentStep(function() {
navigateNext(configuredSteps, currentStep);
});
}
},
validateCurrentStep: function(callback) {
var currentStep = this.currentStep;
if (this.currentScope.form) {
validator.validate(this.currentScope, function() {
validateServerSide(currentStep, callback);
});
} else {
validateServerSide(currentStep, callback);
}
},
getCurrentStep: function() {
return getStepByPath(this.configuredSteps, $location.path().substring(1));
},
reset: function() {
_.each(this.configuredSteps, function(step) { step.visited = false; });
this.firstStep.visited = true;
navigateTo(this.firstStep);
}
};
});

Angular JS: update controller when data change in second controller

what i m doing:
simple html file shows first page , in this page i have one title and button, initially i set $scope.index = 0. so, we set first position of array. when we click on next button it finds firstCtrl and first.html page. in this controller i update $scope.index by 1. so, my question is when i update $scope.index of myCtrl then $scope.index is changed on another controller i wants to change myCtrl. is it possible ? if it is then help me.
index.html:
<body ng-controller="myCtrl">
<div id="navbar">
<div class="setToggle">
<input id="slide-sidebar" type="checkbox" role="button" />
<label for="slide-sidebar"><span class="glyphicon glyphicon-menu-hamburger"></span></label>
</div>
<div class="setQuestion">
<h2>{{surveys[index].questionTitle}}</h2>
</div>
</div>
<div class="content-wrapper" class="container-fluid">
<div class="sidebar-left">
<div class="first">
<ul ng-repeat="cat in surveys[index].category" class="list-unstyled" ng-hide="checkSubCategoryValueIsNull.length">
<li class="category">
<a ng-click="expand=!expand">
<span class="glyphicon" ng-class="{'glyphicon-plus': !expand, 'glyphicon-minus': expand}">
{{cat.categoryName}}
</span>
</a>
</li>
<ul ng-repeat="subcategory in cat.categoryItemDto" class="list-unstyled">
<li ng-show="expand">
<label class="label-style-change">
<input type="checkbox" ng-click="toggleSelectionCheckbox(surveys[index], subcategory)" ng-model="subcategory.selectValue" ng-disabled="disableCheckbox">
<span class="subcategory-item" ng-disabled="disableCheckbox">{{subcategory.subCategoryName}}</span>
</label>
</li>
</ul>
</ul>
</div>
<div class="second">
<input type="button" name="Submit" value="Submit" ng-click="submitSelection()" ng-hide="hideSubmitButton" ng-disabled="!selections[index].length">
<input type="button" name="Edit" value="Edit" ng-click="EditSelection()" ng-show="hideEditButton">
</div>
</div>
<div class="portfolio">
<div id="main">
<div ng-view></div>
</div>
</div>
</div>
</body>
controller.js
(function() {
var app = angular.module("app.controllers", ["app.service"]);
app.controller("myCtrl", ["$scope", "$http", "$location", "$timeout", "surveyService", "Data",
function ($scope, $http, $location, $timeout, surveyService, Data) {
surveyService.getData(function(dataResponse) {
$scope.surveys = dataResponse;
$scope.selections = [];
/* create 2d array mannually */
var numInternalArrays = $scope.surveys.length;
for (var i = 0; i < numInternalArrays; i++) {
$scope.selections[i] = [];
};
$scope.index = 0;
var toggleCheckboxFlag = 0;
/* PRIVATE FUNCTION
for find value from selections array and replace it
*/
function findAndRemove(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
array.splice(index, 1);
toggleCheckboxFlag = 1;
}
});
}
$scope.toggleSelectionCheckbox = function (QuestionId, value) {
toggleCheckboxFlag = 0;
if (!value) return;
findAndRemove($scope.selections[$scope.index], 'categoryId', value.subCategoryId);
if (toggleCheckboxFlag != 1) {
$scope.selections[$scope.index].push({
questionId: QuestionId.questionId,
categoryId: value.subCategoryId,
categoryName: value.subCategoryName,
storeId: 1,
comment: ""
});
}
};
$scope.submitSelection = function() {
$scope.value = $scope.selections[$scope.index];
$scope.hideSubmitButton = true;
$scope.disableCheckbox = true;
$scope.hideEditButton = true;
$location.path("/question/1");
}
});
$scope.EditSelection = function() {
$scope.hideEditButton = false;
$scope.hideSubmitButton = false;
$scope.disableCheckbox = false;
$scope.value = false;
}
$scope.$watch('index', function (newValue, oldValue) {
if (newValue !== oldValue) Data.setIndex(newValue);
});
console.log("controller", Data.getIndex())
}]);
})();
app.js
var app = angular.module('app', ['ngRoute','app.service', 'app.controllers']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/question/1', {
templateUrl: 'views/first.html',
controller: 'sidebarCtrl'
})
.when('/question/2', {
templateUrl: 'views/second.html',
controller: 'mainCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
first.html
<div id="content-wrapper" ng-show="value">
<div class="col-lg-offset-1 col-lg-8 col-md-12 col-sm-12 col-xs-12">
<h2 class="subCategoryLabel"><span class="label">{{value[inc].categoryName}}</span></h2>
</div>
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4">
<button class="btnNext" ng-hide="inc == 0" ng-click="prev()">
<i class="glyphicon glyphicon-menu-left"></i>
</button>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4">
<form name="myForm">
<div ng-repeat="item in surveys[index].optionCategoryItemDto" class="formStyle">
<label class="text-center">
<input type="radio" name="radio" id="{{item.itemId}}" ng-value="item.itemId" ng-model="selections[index][inc].answer" required>
{{item.itemName}}
</label>
</div>
<br/>
<br/>
</form>
</div>
<div class="col-lg-3 col-lg-offset-1 col-md-offset-1 col-md-3 col-sm-4 col-xs-4">
<button class="btnNext" ng-hide="selections[index].length == inc + 1" ng-disabled="myForm.radio.$error.required" ng-click="next()">
<i class="glyphicon glyphicon-menu-right"></i>
</button>
<button class="btnNext" ng-show="selections[index].length == inc + 1" ng-disabled="myForm.radio.$error.required" ng-click="nextQuestion()">
<i class="glyphicon glyphicon-forward"></i>
</button>
</div>
</div>
<div class="col-lg-offset-3 col-lg-4 col-md-offset-3 col-md-6 col-sm-offset-3 col-sm-6 col-xs-4">
<textarea type="text" id="text" class="form-control txtArea" ng-model="selections[index][inc].comment" placeholder="Write comment..."></textarea>
</div>
</div>
sidebarCtrl.js
in this controller i update $scope.index when we call nextQuestion(). here $scope.index increment by one and $watch function also get latest value of index. but myCtrl is not update. i wants to update myCtrl.
(function() {
var app = angular.module("app.controllers");
app.controller("sidebarCtrl", ['$scope', "$location", "Data", function($scope, $location, Data) {
$scope.inc = 0;
$scope.next = function() {
$scope.inc += 1;
}
$scope.prev = function() {
$scope.inc -= 1;
}
$scope.nextQuestion = function() {
$scope.index += 1;
$location.path("/question/2");
}
$scope.$watch('index', function (newValue, oldValue) {
console.log("SASAS", newValue)
if (newValue !== oldValue) Data.setIndex(newValue);
});
}]);
})();
service.js
(function() {
var app = angular.module("app.service", []);
app.service("surveyService", function($http) {
this.getData = function (callbackFunc) {
$http({
method: "GET",
data: {something: true},
contentType: 'application/json',
dataType: 'jsonp',
url: "http://localhost:8080/TheSanshaWorld/sfcms/fetch-survey-details"
}).success(function(data){
callbackFunc(data);
}).error(function(){
alert("error");
});
};
this.setData = function(value) {
if (confirm('Do you wanna to submit?')) {
$http.post("http://localhost:8080/TheSanshaWorld/sfcms/save-survey-result-data", value).success(function(data, status) {
window.open("../index.html","_self");
});
} else {
return false;
}
};
});
app.factory('Data', function () {
var data = {
Index: ''
};
return {
getIndex: function () {
return data.Index;
},
setIndex: function (index) {
data.Index = index;
console.log("service", data.Index)
}
};
});
})();
Because sidebarCtrl is nested within myCtrl, therefore you can reach myCtrl $scope.index from sidebarCtrl using it $scope.$parent.index,
Try it by test: add any parameter value to myCtrl $scope.name='Bob';
then log it in sidebarCtrl console.log($scope.$parent.name); you should see printed 'Bob'. Do the same with index.

how to make dynamic 5 star rating using angularjs?

I have 3 Questions each i have given 5 stars,after user submit i need to convert to 5 how to do this using this formula x1w1 + x2w2 + x3w3 ... xnwn/Total.
http://help.surveymonkey.com/articles/en_US/kb/What-is-the-Rating-Average-and-how-is-it-calculate.i have done something but its not right way i think so?
//--------------------------------------review controller--------------
.controller('ReviewCtrl', [
'$scope', '$http', '$location', '$window',
function($scope, $http, $location, $window) {
$scope.rating1 = {};
$scope.rating2 = {};
$scope.rating3 = {};
$scope.isReadonly = true;
$scope.rateFunctionone = function(rating) {
window.localStorage.setItem("rating1", rating);
};
$scope.rateFunctiontwo = function(rating) {
window.localStorage.setItem("rating2", rating);
};
$scope.rateFunctionthree = function(rating) {
window.localStorage.setItem("rating3", rating);
};
$scope.submit = function() {
var bookingid= window.localStorage.getItem("reviewbookingid");
var storeid = window.localStorage.getItem("reviewstoreid");
var cusname = window.localStorage.getItem("username").replace(/\"/g, "");
var rating1 = window.localStorage.getItem("rating1");
var rating2 = window.localStorage.getItem("rating2");
var rating3 = window.localStorage.getItem("rating3");
var totrating = (parseInt(rating1) + parseInt(rating2) + parseInt(rating3)) / 15;
console.log(totrating);
$http.get('******').success(function(data, response) {
var totcustomer = data.length + 1;
var totcustreview =data.length;
console.log(totcustreview);
if (data.length == 0) {
var caltotrating = (0 + totrating) / totcustomer;
} else
{
var caltotrating = (parseInt(data[0].Rating) + parseInt(totrating)) / totcustomer;
}
var credentials = {};
credentials = {
"Customet_Name": cusname,
"Timely_delivery": rating1,
"Quality_of_service": rating2,
"Value_for_money": rating3,
"Average": totrating,
"Rating": caltotrating,
"Comments": $scope.command,
"Booking_id": bookingid,
"Store_id": storeid
}
var scredentials = {};
scredentials = {
"S_Ratings": caltotrating,
"S_Noofpeoplegivenreview": totcustomer,
}
$http.put('***').success(function(data, status, headers, config, response) {
});
$http.post('***').success(function(data, status, headers, config, response) {
});
});
}
}
])
//---------------------------------------------------------------------
.directive("starRating", function() {
return {
restrict: "EA",
template: "<ul class='rating' ng-class='{readonly: readonly}'>" +
" <li ng-repeat='star in stars' ng-class='star' ng-click='toggle($index)'>" +
" <i class='ion-star'></i>" + //&#9733
" </li>" +
"</ul>",
scope: {
ratingValue: "=ngModel",
max: "=?", //optional: default is 5
onRatingSelected: "&?",
readonly: "=?"
},
link: function(scope, elem, attrs) {
if (scope.max == undefined) {
scope.max = 5;
}
function updateStars() {
scope.stars = [];
for (var i = 0; i < scope.max; i++) {
scope.stars.push({
filled: i < scope.ratingValue
});
}
};
scope.toggle = function(index) {
if (scope.readonly == undefined || scope.readonly == false) {
scope.ratingValue = index + 1;
scope.onRatingSelected({
rating: index + 1
});
}
};
scope.$watch("ratingValue", function(oldVal, newVal) {
if (newVal) {
updateStars();
}
});
}
};
})
<ion-content ng-controller="ReviewCtrl" >
<form data-ng-submit="submit()">
<div class="row">
<div class="col item item-divider">Timely Delivery </div>
<div class="col item item-divider">
<div star-rating ng-model="rating1" max="5" on-rating-selected="rateFunctionone(rating)"></div>
</div>
</div>
<br>
<div class="row">
<div class="col item item-divider">Quality of Service </div>
<div class="col item item-divider">
<div star-rating ng-model="rating2" max="5" on-rating-selected="rateFunctiontwo(rating)"></div>
</div>
</div>
<br>
<div class="row">
<div class="col item item-divider"> Value for Money </div>
<div class="col item item-divider">
<div star-rating ng-model="rating3" max="5" on-rating-selected="rateFunctionthree(rating)"></div>
</div>
</div>
<br>
<ul >
<li class="item item-checkbox">
<label class="checkbox checkbox-energized">
<input type="checkbox" ng-model="recommend" ng-true-value="'yes'" ng-false-value="'no'">
</label>
Would you recommend this dealer to your friends?
</li>
</ul>
<label class="item item-input item-floating-label" >
<span class="input-label">Say! how you feel</span>
<textarea placeholder="Say! how you feel" rows="4" ng-model="command"></textarea>
</label>
<div class="padding">
<button class="button button-full button-stable" type="submit" > Submit
</button>
</form>
</div>
</ion-content>
Use this RateIt for rating its quite easy you just need bower to install it and include the js and css.

Angular ui-select2 values not being detected in scope

For a bit of background, I am trying to create a simple form that will allow a user to send a message. I am using ui-select2 to allow the user to search for the message recipient, but for some reason selecting the user doesn't update the necessary scope variable.
<div ng-show="message_page == 'Compose'" ng-controller="userctrl" class="col-sm-9">
<section class="panel">
<header class="panel-heading wht-bg">
<h4 class="gen-case"> Compose Mail
<form action="#" class="pull-right mail-src-position">
</form>
</h4>
</header>
<div class="panel-body">
<div class="compose-mail">
<form role="form-horizontal" method="post">
<div class="form-group">
<label for="to" class="">To:</label>
<select style="min-width:150px" ui-select2 ng-model="message.recipient" data-placeholder="Who do you want to message?">
<option ng-repeat="user in users" value="user.id">{{user.name}}</option>
</select>
{{message}}
</div>
<div class="form-group">
<label for="subject" class="">Subject:</label>
<input ng-model="message.subject" type="text" tabindex="1" id="subject" class="form-control">
</div>
<div class="compose-editor">
<textarea ng-model="message.content" class="wysihtml5 form-control" rows="9"></textarea>
</div>
<div class="compose-btn">
<button ng-click="send()" class="btn btn-primary btn-sm" onclick="$('#cc').parent().addClass('hidden'); $('#cc').focus();"><i class="fa fa-check"></i> Send</button>
</div>
</form>
</div>
</div>
</section>
</div>
</div>
This is the relevant html code (which is a template for a directive) and here is the directive code:
.directive('messageslist', function(){
return{
templateUrl: 'message-list-template.html',
restrict: 'E',
controller: function(Auth, $scope, $rootScope, $timeout, ListMessagesSvc, SingleMessageSvc, MessageCreateSvc){
$scope.message = {};
var messagesLoader = function(){
ListMessagesSvc.query().$promise.then(function(data){
$rootScope.messages = $scope.messages = data;
var unread_messages_count = 0;
for(var i = 0; i < $scope.messages.length; i++){
if($scope.messages[i].type == "unread"){
unread_messages_count++;
}
}
console.log("There are " + unread_messages_count + " unread messages");
$rootScope.unread_messages_count = $scope.unread_messages_count = unread_messages_count;
})
}
$scope.refresh_messages = function(){
if(Auth.isAuthenticated()){
messagesLoader();
}
}
$scope.open_message = function(message_id){
console.log("The message is being opened" + message_id);
SingleMessageSvc.get({id: message_id}).$promise.then(function(data){
$scope.current_message = data;
})
$scope.message_page = "Single";
}
$scope.inbox = function(){
if(Auth.isAuthenticated()){
messagesLoader();
}
$scope.message_page = "Inbox";
}
$scope.compose = function(){
$scope.message_page = "Compose";
}
$scope.send = function(){
console.log($scope.message);
MessageCreateSvc.save($scope.message).$promise.then(function(data){
$scope.message = null;
$scope.message_page = "Inbox";
});
}
$scope.discard = function(){
$scope.message = null;
$scope.message_page = "Inbox";
}
var infiniteLoop = function(){
$timeout(function(){
if(Auth.isAuthenticated()){
messagesLoader();
}
infiniteLoop();
}, 60000);
}
if(Auth.isAuthenticated()){
messagesLoader();
}
infiniteLoop();
$scope.message_page = "Inbox";
}
}
})
I have tried the directive both with and without the link element and the scope element, but these changes didn't seem to make any difference. I have also attempted to output the contents of the message object, and while it does pick up changes to the content and the topic it doesn't pick up changes to the recipient. Also, I have successfully used ui-select2 elsewhere in my application so I am not sure what it different about this instance.
Let me know if you need any more information.
You have to change this:
value="user.id"
to this:
value="{{user.id}}"
or this:
ng-value="user.id"
Otherwise all the values will be 'user.id'
For anyone with a similar issue to myself, try removing the controller element. Fixed the issue for me!

ng-click ng-keypress passing form data not working

Im trying to send data from user input to display on the screen when button click.
The problem is that if i click on the button it simply passes to the next value without gathering the information and displaying in the screen. If i press ENTER it works how it should. i have searched all over internet several examples but simply couldnt get it to work. im using at the moment :
<button class="btn btn-lg btn-default next bt_submits" type="button" ng-click="addData(newData)">
<span class="bt_arrow"></span>
</button>
full html:
<div class="boxContent col-md-12">
<h1>{{lang.sec101.h1}}</h1>
<div class="col-md-12 lineBorder noPad" >
<div class="box1">
<p>
{{lang.sec101.title}}
</p>
</div>
<!-- dynamic form -->
<div class="col-md-12 borderBox boxLeft bg_box">
<form novalidate name="addForm">
<div class="boxLeft" ng-show="Question != ''">
<div ng-show="Question.infotip != 'yes'">
<h1 class="heading_left">{{Question.ask}}</h1>
</div>
<div ng-show="Question.infotip == 'yes'">
<h1 class="heading_left info">{{Question.ask}}
<span class="infotip yourData" tooltip-placement="top" tooltip-trigger="click" tooltip="{{Question.infotipText}}"></span>
</h1>
</div>
</div>
<div class="boxRight" ng-show="Question != ''">
<button class="btn btn-lg btn-default next bt_submits" type="button" ng-click="addData(newData)">
<span class="bt_arrow"></span>
</button>
</div>
<div class="boxRejestracjaInput">
<!-- <div id="legg-select" ng-if="Question.type === 'select'">
<select ng-options="opt.val for opt in Question.options" name="{{Question.name}}" ng-model="value" ng-keypress="enter($event,value.val)"></select>
</div> -->
<div class="newSelect">
<label ng-if="Question.type === 'select'">
<select ng-options="opt.val for opt in Question.options" name="{{Question.name}}" ng-model="value" ng-keypress="enter($event,value.val)"></select>
</label>
</div>
<input
ng-if="Question.type === 'text'"
type="{{Question.type}}"
name="institutionName"
class="inputName"
value="{{Question.value}}"
ng-model="value"
ng-minlength="{{Question.min}}"
ng-maxlength="{{Question.max}}"
ng-keypress="enter($event,value)"
placeholder="{{Question.placeholder}}"
ng-pattern="{{Question.pattern}}" />
<!-- <div class="custom-error institution" ng-show="addForm.institutionName.$error.minlength || addForm.institutionName.$error.maxlength">
Minimum {{Question.min}} znaków
</div> -->
<!-- <div class="custom-error institution" ng-show="addForm.institutionName.$error.maxlength">
Max {{Question.max}} znaków
</div> -->
<div class="custom-error institution" ng-show="addForm.institutionName.$error.pattern || addForm.institutionName.$error.maxlength || addForm.institutionName.$error.minlength">
{{Question.copy}}
</div>
</div>
</form>
</div>
<p>
{{lang.sec101.title2}}
</p>
<a href="rejestracja_10edit.html" class="btn btn-lg btn-default bt_edit" type="button">
{{lang.sec101.title3}}<span class="btn_bg_img"></span>
</a>
</div>
<div class="col-md-12 noPad" ng-repeat="sek in formOut">
<h3 class="daneHeading">{{sek.name}}</h3>
<div class="row">
<div class="col-md-12" >
<div class="col-md-4 col-sm-6 boxContent3 boxes" ng-repeat="row in sek.data">
<span class="leftBoxContrnt">{{row.shortAsk}}</h4></span>
<h4 class="rightBoxContrnt">{{row.value}}</h4>
</div>
</div>
</div>
</div>
<!-- <div class="row col-md-12" >
<h3 class="daneHeading">Hasło</h3>
</div>
<div class="row">
<div class="col-md-12 " >
<div class="col-md-4 col-sm-6 boxContent3">
<span class="leftBoxContrnt">Test</h4></span><span class="blueTxt"> *</span>
<h4 class="rightBoxContrnt">Test</h4>
</div>
</div>
</div> -->
</div>
my controller:
var app = angular.module('app', ['ngAnimate', 'ngCookies', 'ui.bootstrap', 'ngSanitize', 'nya.bootstrap.select', 'jackrabbitsgroup.angular-slider-directive']);
// var rej10_Controller = function($scope, $http, $cookieStore, $timeout, limitToFilter) {
app.controller('rej10_Controller', ['$scope', '$http', '$cookieStore', '$sce', '$timeout', 'limitToFilter',
function($scope, $http, $cookieStore, $sce, $timeout, limitToFilter) {
var view = 10,
arr,
data,
counterSection = 0,
counterAsk = 0;
$scope.opts = {};
$scope.slider_id = 'my-slider';
$scope.opts = {
'num_handles': 1,
'user_values': [0, 1],
'slider_min': 0,
'slider_max': 1,
'precision': 0,
};
/* language */
if (!$cookieStore.get('lang'))
$cookieStore.put('lang', 'pl');
var lang = $cookieStore.get('lang');
$scope.language = lang;
$scope.setLang = function(data) {
$cookieStore.put('lang', data);
$http.get('../widoki/json/lang/' + data + '/rej_' + view + '.json').
success(function(data, status, headers, config) {
$scope.lang = data;
$scope.Question = $scope.lang.formIn.sekcja[counterSection].data[counterAsk];
console.log($scope.lang);
}).
error(function(data, status, headers, config) {
console.log('error load json');
});
$scope.language = data;
};
/* get language pack */
$http({
method: 'GET',
url: '../widoki/json/lang/' + lang + '/rej_' + view + '.json'
}).
success(function(data, status, headers, config) {
$scope.lang = data;
$scope.Question = $scope.lang.formIn[counterSection].data[counterAsk];
$scope.langLen = $scope.lang.formIn.length;
}).error(function(data, status, headers, config) {
console.log('error load json');
});
/* dynamic form */
$scope.enter = function(ev, d) {
if (ev.which == 13) {
$scope.addData(d);
}
};
$scope.addData = function(data) {
var newData = {};
/* latamy po id sekcji i po id pytania */
if (!$scope.formOut) {
$scope.formOut = [];
}
/* budowanie modelu danych wychodzcych */
newData = {
sekcja: counterSection,
name: $scope.lang.formIn[counterSection].name,
data: []
};
console.log(name);
if (!$scope.formOut[counterSection]) {
$scope.formOut.push(newData);
}
$scope.formOut[counterSection].data.push($scope.Question);
$scope.formOut[counterSection].data[counterAsk].value = data;
counterAsk++;
// zmieniamy sekcje
if (counterAsk == $scope.lang.formIn[counterSection].data.length) {
counterAsk = 0;
counterSection++;
}
if (counterSection == $scope.lang.formIn.length) {
$scope.Question = '';
/* zrobic ukrycie pola z formularza */
} else {
$scope.Question = $scope.lang.formIn[counterSection].data[counterAsk];
}
/* konwertowanie do jsona */
//var Json = angular.toJson($scope.formOut);
//console.log(Json);
};
$scope.submit = function() {
alert('form sent'); /* wysĹanie formularza */
};
$scope.getClass = function(b) {
return b.toString();
};
}
]);
app.directive('ngEnter', function() {
return function(scope, element, attrs) {
element.bind("keydown keypress", function(event) {
if (event.which === 13) {
scope.$apply(function() {
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
});
app.config(['$tooltipProvider',
function($tooltipProvider) {
$tooltipProvider.setTriggers({
'mouseenter': 'mouseleave',
'click': 'click',
'focus': 'blur',
'never': 'mouseleave',
'show': 'hide'
});
}
]);
var ValidSubmit = ['$parse',
function($parse) {
return {
compile: function compile(tElement, tAttrs, transclude) {
return {
post: function postLink(scope, element, iAttrs, controller) {
var form = element.controller('form');
form.$submitted = false;
var fn = $parse(iAttrs.validSubmit);
element.on('submit', function(event) {
scope.$apply(function() {
element.addClass('ng-submitted');
form.$submitted = true;
if (form.$valid) {
fn(scope, {
$event: event
});
}
});
});
scope.$watch(function() {
return form.$valid
}, function(isValid) {
if (form.$submitted == false)
return;
if (isValid) {
element.removeClass('has-error').addClass('has-success');
} else {
element.removeClass('has-success');
element.addClass('has-error');
}
});
}
};
}
};
}
];
app.directive('validSubmit', ValidSubmit);
I cant figure out what is the problem.
Thanks in advance.
Try changing your ngClick button handler to an ngSubmit form handler and wiring that up. You didn't say what browser you're using, but most of them auto-submit forms on an ENTER keypress unless you trap it (which you aren't). Clicking a button won't do this.

Resources