angularjs enable/disable button on a directive - angularjs

I'm new to Angular and I've been stuck on this for a day already. I have content for a modal being pulled with a directive which contains a simple form. I want to keep end-users from double clicking when submitting the form. So far this is the closets I've gotten. The content and modal pull up ok, when the button is clicked it gets disabled, the ajax calls is performed ok, the modal hides again, but the button remains disabled. When I mention button I refer to the button on the modal content with id="submitTradeForm"
This is the content in the modal
<div class="cdc-modal">
#using (#Html.BeginForm("_CreateTrade", "Employees", FormMethod.Post, new { #class = "cdc-form", #id = "createTradeForm" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(null, new { #class="text-danger" })
<div class="form-group">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", #placeholder = "trade" })
</div>
<div class="modal-footer">
<input id="submitTradeForm" type="button" ng-click="createTrade()" ng-disabled="isProcessing" class="btn cdc-button" value="Add new trade" />
</div>
}
</div>
This is the JS/Angular code
//********************** ANGULARJS - BEGIN *****************************************//
var app = angular.module('empApp',[]);
app.controller('empCtrl', function ($scope) {
});
app.directive('empModal',function($compile){
return {
restrict: 'EA',
templateUrl: '#Url.Content("~/Employees/_CreateTrade")',
replace: true,
controller: function ($scope) {
},
compile: function (tElement, tAttr) {
var contents = tElement.contents().remove();
var compiledContents;
return function (scope, iElement, iAttr) {
if (!compiledContents) {
compiledContents = $compile(contents);
}
compiledContents(scope, function (clone, scope) {
iElement.append(clone);
});
scope.createTrade = function () {
scope.isProcessing = true;
var form = $("#createTradeForm");
$.ajax({
cache: false,
async: true,
type: "POST",
url: form.attr("action"),
data: form.serialize(),
success: function (data) {
$("#createTradeModal").modal("hide");
//empty the container
$("#trades").html("");
var sel = $("#trades");
var newCont = "";
for (var i = 0; i < data.length; i++) {
sel.append('<option value="' + data[i].TradeId + '">' + data[i].Name + '</option>');
}
scope.isProcessing = false;
}
}).complete(function () {
scope.isProcessing = false;
console.log('completed');
console.log(scope.isProcessing);
});
};
};
}
}
});
//********************** ANGULARJS - END *****************************************//
This is in the main View
<div ng-app="empApp" ng-controller="empCtrl" class="container">
<div class="row">
<div class="col-sm-12">
<h3>Add New Employee</h3>
#using (Html.BeginForm("Create", "Employees", FormMethod.Post, new { #id = "createEmployeeForm"}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(null, new { #class="text-danger" })
#Html.Hidden("selectedTrades", null, new { #id="selectedTrades" })
<div class="row" style="margin-bottom:15px;">
<div class="form-group col-sm-12">
#Html.TextBoxFor(m => m.EmployeeNumber, new { #placeholder = "employee number", #class = "form-control pull-left col-sm-8" })
<span style="min-width:160px;margin-top:5px;" class="col-sm-4 cdc-text pull-left">last entered: #lastentered</span>
</div>
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.FirstName, new { #placeholder = "first name", #class = "form-control", #id = "firstname" })
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.LastName, new { #placeholder = "last name", #class = "form-control", #id = "lastname" })
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.StoreAs, new { #placeholder = "store as", #class = "form-control", #id = "storeas" })
</div>
<div class="row" style="padding-bottom:15px;min-width:320px !important;">
<div id="selectContainer" class="col-sm-8 pull-left" style="max-width:280px;">
<select id="trades" multiple="multiple">
#if (Model.Trades.Any())
{
foreach (CDCManagement.Trade trade in Model.Trades)
{
<option value="#trade.TradeId">#Html.Encode(trade.Name)</option>
}
}
</select>
</div>
<a href="#" onclick="addTrade()" data-toggle="modal" data-target="#createTradeModal">
<span class="glyphicon glyphicon-plus cdc-icon col-sm-4 pull-left cdc-icon-push" style="padding-left:0;"></span>
</a>
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.PhoneNumber, new { #placeholder = "phone number", #class = "form-control" })
</div>
<div class="form-group">
#Html.TextAreaFor(m => m.Comments, new { #placeholder = "comments", #class = "form-control" })
</div>
<div class="form-group">
<input id="createButton" type="button" onclick="processForm()" class="btn cdc-button" value="Add New Employee" />
</div>
}
</div>
</div>
<!-- modal begin (add title) -->
<div class="modal fade" id="createTradeModal">
<div id="modal-dialog" class="modal-dialog">
<div id="modal-content" class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Add New Trade</h4>
</div>
<div id="modal-body" class="modal-body">
<emp-modal></emp-modal>
</div>
</div>
</div>
</div>
<!-- modal end -->
</div>

You're mixing jQuery and angular, and have hit the very common pitfall of using a jQuery event to trigger something in angular, in this case an AJAX response.
Whenever something changes that angular needs to know about, you need to trigger a $digest. There are lots of resources on the web about this, and I strongly recommend you get a good understanding of the angular lifecycle before writing any more code.
To fix your problem, you should simply be able to change the following line:
scope.isProcessing = false;
To
scope.$apply( function() {
isProcessing = false;
});
This tells angular you're changing something that it should know about, and it runs its digest loop which updates all of the views accordingly. This will re-enable the button that you previously disabled.
As an aside: I'm not sure if you're refactoring an existing application to use angular, or starting from scratch. Either way, you should try to remove your dependence on jQuery unless there is a specific reason for it. This stackoverflow question is a great reference that should get you thinking about things 'the angular way'. If you can get your head around this, it will pay dividends.

Related

two way binding not working even with dot notation

I'm starting with AngularJS and I am using a controller variable to navigate an array of questions, and it is working when using nextQuestion function, index gets updated and the next question is shown in the view, but if I try to obtain the same value (index) in a different function, it always returns 0.
I have seen on other questions that you should use an object to contain the variable to not manipulate primitive types directly in the controller, but it still does not work.
My controller:
myApp.controller('SurveyController',['$scope','$http', '$location','$routeParams','surveyMetrics','DataService',function($scope,$http, $location,$routeParams,surveyMetrics,DataService){
console.log('LOADED QUIZ CONTROLLER');
var vm = this;
vm.scope = {
index: 0
};
vm.surveyMetrics = surveyMetrics;
vm.surveyQuestions = DataService.surveyQuestions;
vm.DataService = DataService;
/*
vm.getQuestions = function(){
$http.get('/api/questions').then(function(response){
$scope.questions = response.data;
});
}
*/
/*
vm.activateSurvey = function(){
surveyMetrics.changeState(true);
}
*/
vm.getCurrentIndex = function(){
return vm.scope.index;
}
vm.nextQuestion = function () {
console.log('NEXT QUESTION!');
console.log('NUMBER OF QUESTIONS: '+ vm.surveyQuestions.length);
var currentIndex = vm.getCurrentIndex();
var newIndex = currentIndex+1;
scope = {};
if (currentIndex == vm.surveyQuestions.length) {
newIndex = vm.surveyQuestions.length -1;
}
vm.scope.index = newIndex;
console.log('Inside Object: '+vm.scope)
console.log('vm.index'+vm.scope.index);
console.log('vm.indexFunction'+vm.getCurrentIndex());
}
/*
vm.previousQuestion = function () {
console.log('PREVIOUS QUESTION!');
console.log('NUMBER OF QUESTIONS: '+ vm.surveyQuestions.length);
if (vm.scope.index == 0) {
vm.scope.index = 0;
}else{
vm.scope.index--;
}
}
*/
vm.activeSurveyQuestion = function(questionId,index){
console.log('question id and index',questionId,index);
if (questionId == index) {
var navBtn = document.getElementById('navBtn_'+index);
navBtn.classList.add('active');
}
}
vm.navigateSurvey = function () {
var answerPane = document.getElementById('answer-pane');
document.onkeydown = function (e) {
console.log('INSIDE KEYDOWN: ')
e.preventDefault();
var pressedKey = e.keyCode;
console.log('PRESSED KEY IN SURVEY: ' + pressedKey);
if (pressedKey === rightArrow) {
console.log('survey - right arrow pressed');
document.getElementById('nextQuestionBtn').click();
console.log('FUCKING INDEX FML!: '+vm.getCurrentIndex()+' | '+vm.scope.index);
var questionType = DataService.getQuestionType(vm.scope.index);
console.log('Survey Controller: question type: '+questionType);
}
if (pressedKey === leftArrow) {
console.log('survey - left arrow pressed');
document.getElementById('previousQuestionBtn').click();
}
(...)
My View:
<!--Satisfaction Survey-->
<div ng-controller="SurveyController as survey" ng-init="survey.getSurvey();">
<!--
<p ng-repeat="question in survey.surveyQuestions" ng-show ="survey.surveyMetrics.surveyActive">
{{question.question}}
</p>
-->
<!--Survey Modal -->
<div class="modal fade" id="surveyModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="text-center"> Customer Satisfaction Survey</div>
<div class="modal-header">
<h4 class="modal-title">{{survey.surveyQuestions[survey.getCurrentIndex()].question}}</h4>
</div>
<div class="modal-body survey" id="answer-pane">
<div class="row">
<div class="col-sm-2 survey-left-arrow" ng-click="survey.previousQuestion();" id="previousQuestionBtn">
<p>‹</p>
</div>
<div class="col-sm-8">
<!-- <p ng-repeat="answer in survey.surveyQuestions[survey.index].answers">{{answer}}</p> -->
<p ng-repeat="answer in survey.surveyQuestions[survey.getCurrentIndex()].answers">
<button type="button" class="btn" id="answerId_{{survey.getCurrentIndex()}}"
ng-class="{'survey-check-box': (survey.surveyQuestions[survey.getCurrentIndex()].type !== 'SingleChoice'),
'survey-btn_{{($index+1)}}': (survey.surveyQuestions[survey.getCurrentIndex()].type === 'SingleChoice')}">
<input type="checkbox" ng-if="survey.surveyQuestions[survey.getCurrentIndex()].type !== 'SingleChoice'"> {{answer}}
</button>
</p>
</div>
<div class="col-sm-2 survey-right-arrow " ng-click="survey.nextQuestion();" id="nextQuestionBtn">
<p>›</p>
</div>
</div>
</div>
<div class="text-center">
<strong> <p>Question: {{survey.surveyQuestions[survey.scope.index].questionNum}} of {{survey.surveyQuestions.length}}</p> </strong>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
<!-- <nav aria-label="Survey navigation">
<ul class="pagination pagination-sm justify-content-center">
<div ng-repeat="question in survey.surveyQuestions" >
<li class="page-item">
<a class="page-link" id = "navBtn_$index" ng-click="survey.index = $index">{{question.id}}</a>
</li>
</div>
</ul>
</nav> -->
</div>
</div>
I would like for the controller to change the variable and the view to update accordingly
Thank you for your time and thank you in advance.
It's 'survey.scope.index' not 'survey.index' in your HTML. I think you may be unclear the difference between using 'this' and '$scope'. You're mixing the two together which is not necessary. I would suggest removing 'scope' and just reference it in your HTML as 'survey.index'.

Angularjs cannot perform crud operations from accordion

I am trying to add a form to a bootstrap accordion and post a text value. Without accordion the form works alright. When i added the form to the accordion i am not able to pass text box value to angularjs controller. Basically i am not able to perform the CRUD operations as i am not able to pass the values. Minimum code related to the issue.
main.html
<div ng-controller="myController">
<accordion class="accordion" close-others="oneAtATime">
<accordion-group ng-repeat="group in groups" is-open="status.isOpen[$index]" >
<accordion-heading>
{{group.groupTitle}} <i class="fa chevron-icon" ng-class="{'fa-chevron-down': status.isOpen[$index], 'fa-chevron-right': !status.isOpen[$index]}"></i>
</accordion-heading>
<div ng-include="group.templateUrl"></div>
</accordion-group>
</accordion>
</div>
controller.js
App.controller('myController', ['$scope', 'Parts', function($scope, Parts) {
var original = $scope.parts;
$scope.submit = function() {
if ($scope.parts.a_id == null) {
$scope.createNewPart();
} else {
$scope.updatePart();
}
};
$scope.createNewPart = function() {
Parts.resource1.create($scope.parts);
};
$scope.updatePart = function() {
Parts.resource2.update($scope.parts)
};
$scope.oneAtATime = true;
$scope.groups = [{
groupTitle: "ADD 1",
templateUrl: "file1.html"
}, {
groupTitle: "ADD 2",
templateUrl: "file2.html"
}];
$scope.status = {
isOpen: new Array($scope.groups.length)
};
for (var i = 0; i < $scope.status.isOpen.length; i++) {
$scope.status.isOpen[i] = (i === 0);
}
} ]);
file1.html
<div>
<form name="myForm" ng-submit="submit()">
<div class="row">
<label class="col-md-2 control-lable" for="part">Add1</label>
<input type="text" ng-model="parts.part" id="part" required />
</div>
<div class="row">
<input type="submit" value="{{!parts.id ? 'Add' : 'Update'}}" ng-disabled="myForm.$invalid">
</div>
</form>
//inside table
<tr ng-repeat="a in availableparts >
<td>{{a.id}}</td>
<td>{{a.apart}}</td>
<td><button type="button" ng-click="editPart(a.id)" >Edit</button>
<button type="button" ng-click="deletePart(a.id)">Remove</button>
</td>
</tr>
</div>
Initially, you need to set $scope.parts to empty object {}, so when you access $scope.parts.id you will have null, instead of error saying id of undefined

How to popup chat window using node.js

I am working on node.js and began to create a chat application I have built it successfully but the problem is that I want the chat window should be open when the client click on the name of the sender(who sent the message to the client).
I will show you the example what I have done till now.
Here you can see that the chat box is already open but I want it should open when a user is selected from "List of users" and the content of chat box should be replaced whenever a new user is selected and previous content should be removed.
Here is my index.html code :
<div class="col-md-4 user-list">
<h2>List of Users</h2>
<ul class="list-group">
<li class="list-group-item"
ng-repeat="user in userList"
ng-class="{ 'active' : user.id == selectedUser.uid}"
ng-click = seletedUser(user.id,user.userName);
ng-style="{
'cursor': user.id === socketId ? 'not-allowed' :'pointer'
}"
>
<span id='{{user.id}}' >{{ user.id === socketId ? 'You': user.userName }}</span>
<span id='{{user.id + "notify"}}' style="color:black; opacity:0.5; font:2px; padding:5px; visibility:hidden;"> {{'typing...'}}</span>
</li>
</ul>
</div>
</div>
<div class="container" id="messages">
<div class="row">
<div class="col-md-8">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span> {{'Chat -' + selectedUser.uname}}
</div>
<div class="panel-body">
<ul class="chat col-md-7"
ng-repeat = "message in messages"
ng-style ="{'float':message.fromid == socketId ? 'left' : 'right'}">
<li>
<div class="clearfix">
<div class="direct-chat-text"
ng-style = "{'background-color': message.fromid == socketId ? '#d9edf7' : '#62f3bc'}"
>
{{message.msg}}
</div>
</div>
</li>
</ul>
<br></br>
</div>
<div class="panel-footer">
<div class="input-group">
<textarea elastic type="text" class="form-control custom-control" ng-model='message' ng-keyup="keyup()" ng-keydown="keydown()" ng-change="change()" placeholder="Type your message here..."></textarea>
<span class="input-group-addon btn btn-primary" ng-click="sendMsg()"><i class="glyphicon glyphicon-send"></i></span>
</div>
</div>
</div>
</div>
</div>
</div>
If you would require any other information related to code please comment.
As I am newbie to node.js so help me to solve my problem.
UPDATE
My script.js code which have sufficient details:
app.controller('app', ($scope,$timeout,socket) => {
$scope.socketId = null;
$scope.selectedUser ={ uid: null, uname: null};
$scope.messages = [];
$scope.msgData = null;
$scope.userList = [];
var TypeTimer;
var TypingInterval = 1000;
$scope.username = window.prompt('Enter Your Name');
if ($scope.username === '') {
window.location.reload();
}
$scope.seletedUser = (id,name) => {
if(id === $scope.socketId)
{
alert("Can't message to yourself.")
}
else
{
$scope.selectedUser =
{
uid: id,
uname: name
}
}
};
$scope.sendMsg = () => {
// const keyCode = $event.which || $event.keyCode;
if ($scope.message !== null && $scope.message !== '' && $scope.selectedUser.uid !== null) {
socket.emit('getMsg',{
toid : $scope.selectedUser.uid,
fromid: $scope.socketId,
msg : $scope.message,
name : $scope.username
});
$timeout.cancel(TypeTimer);
TypeTimer=$timeout( function(){
socket.emit('getTypingNotify',{
toid : $scope.selectedUser.uid,
fromid: $scope.socketId,
msg:"hidden"
});
});
$scope.message = null;
console.log($scope.selectedUser.uid);
}
else
{
alert("enter a message or select a User to send message");
}
};
socket.emit('username',$scope.username);
socket.on('userList', (userList,socketId) => {
if($scope.socketId === null){
$scope.socketId = socketId;
}
$scope.userList = userList;
});
socket.on('exit', (userList) => {
$scope.userList = userList;
});
socket.on('setMsg',(data) => {
document.getElementById(data.fromid+'notify').style.visibility= data.msg;
});
socket.on('sendMsg', (data) => {
//console.log('send');
$scope.messages.push(data);
});
my understanding is u want to show a pop up on click of a button or some text box u can use angular bootstarp model as shown here
"https://plnkr.co/edit/?p=preview"
and control the close and open in angularjs contoller and send the chat details too server side
After searching some tutorials and questions(on StackOverflow) I found a way and going to share with you all.
I created a directory name "open" and an attribute visible of this "open" directive to show and hide the dialog.
app.directive('open',function() {
return {
restrict: 'E',
template: `<div class="container">
<div class="row">
<div class="col-md-8">
<div class="panel panel-primary">
<div class="panel-heading">
<span class="glyphicon glyphicon-comment"></span>{{"Chat -" + selectedUser.uname}}
</div>
<div class="panel-body">
<div ppp-chat></div>
<br></br>
</div>
<div class="panel-footer">
<div class="input-group">
<textarea msd-elastic type="text" class="form-control custom-control" ng-model="message" ng-keyup="keyup()" ng-keydown="keydown()" ng-change="change()" placeholder="Type your message here..."></textarea>
<span class="input-group-addon btn btn-primary" ng-click="sendMsg()"><i class="glyphicon glyphicon-send"></i></span>
</div>
</div>
</div>
</div>
</div>
</div>`,
replace:true,
scope:false,
link: function postLink(scope,element,attrs) {
scope.$watch(attrs.visible,function(value){
if(value == true)
{
$(element).show();
}
else
$(element).hide();
});
$(element).on('show.bs.open',function() {
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('hidden.bs.open',function() {
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
}
};
});
And a method in controller to toggle the chat window(hide or show)
$scope.toggleChat = () => {
$scope.showChat = false;
$scope.showChat = !$scope.showChat;
};
this toggleChat is used to change the value of showChat scope variable that is used to turn on(off) the visibility of chat box by alterating the showChat value as true or false.
In html I have replaced my id="messages" element( with its child and subchild) with
<open visible="showChat">
</open>

AngularJS: upload file inside modal-ui-bootstrap

I have an angular modal-ui, in it I upload file. The problem is that for some reason the <input> of the file doesn't triggers the app directive. The directive returns the file name and size when the <input> being changed.
this is the result I want to get:
example
I really tried already any thing, but still for some reason I can't see in the <span> the file name.
The html file :
<form novalidate ng-submit="add(Form.$valid)" name="Form">
<div class="modal-header col-lg-12">
<h3 class="col-lg-4 col-lg-offset-4">add file</h3>
</div>
<div class="modal-body">
<div class="panel-body">
<div class="row">
<div class="form-group col-lg-8" ng-class="{'has-error': notPass && Form.fileName.$invalid}">
<label class="control-label label-add-card" for="fileName">name</label>
<input class="input-add-card form-control " id="fileName" name="fileName" type="text" ng-model="fileName" ng-pattern="/^[a-z1-9]{10,}$/" ng-required="true">
<p ng-show="notPass && Form.fileName.$invalid" class="help-block">not good</p>
</div>
</div>
<div class="row">
<div class="form-group col-lg-8" ng-class="{'has-error':notPass && Form.fileExplain.$invalid}">
<label class="control-label label-add-card" for="fileExplain">explain</label>
<textarea class="input-big form-control " id="fileExplain" name="fileExplain" type="text" ng-model="fileExplain" ng-pattern="/^[a-z1-9]{1,}$/" ng-required="true"></textarea>
<p ng-show="notPass && Form.fileExplain.$invalid" class="help-block">not good</p>
</div>
</div>
<div>
<div class="form-group col-lg-12" ng-class="{'has-error':notPass && Form.uploadDownloads.$invalid}">
<input ng-model="uploadDownloads" type="file" fd-input file-name="fileName" />
<input class="btn btn-primary" type="button" value="choose" onclick="$(this).parent().find('input[type=file]').click();"/> <!-- on button click fire the file click event -->
<span class="badge badge-important">{{fileName}}</span>
<p ng-show="notPass && Form.uploadDownloads.$invalid" class="help-block">please choose</p>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success col-lg-12 btn-modal-costume">add</button>
</div>
</form>
the modal controller:
/**
* Created by Ariel on 22/11/2015.
*/
app.controller('uploadDownloadsController',function($scope,$modalInstance ){
app.directive('fdInput', fdInput);
function fdInput() {
return {
scope: {
fileName: '='
},
link: function(scope, element, attrs) {
element.on('change', function(evt) {
var files = evt.target.files;
console.log(files[0].name);
console.log(files[0].size);
scope.fileName = files[0].name;
scope.$apply();
});
}
}
};
$scope.fileName = '';
$scope.add = function(valid){
if(valid){
$scope.data = 'none';
var f = document.getElementById('uploadDownloads').files[0];
var r = new FileReader();
r.onloadend = function(e){
$scope.data = e.target.result;
$scope.notPass = false;
$modalInstance.close({
'data':$scope.data,
'fileName':$scope.fileName,
'fileExplain':$scope.fileExplain
});
};
/*activate the onloadend to catch the file*/
r.readAsBinaryString(f);
} else {
$scope.notPass = true;
}
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});
here is how I have done it :
the html :
<form novalidate ng-submit="add(Form.$valid)" name="Form">
.
.
.
<div>
<div class="form-group col-lg-12" ng-class="{'has-error':notPass && Form.uploadDownloads.$invalid}">
<input ng-model="uploadDownloads" class="form-control-file" id="uploadDownloads" type="file" fd-input file-names="fileNames" />
<input class="btn btn-primary" type="button" value="choose" ng-click="choose()"/> <!-- on button click fire the file click event -->
<span class="badge badge-important">{{fileNames}}</span>
<p ng-show="notPass && Form.uploadDownloads.$invalid" class="help-block">you have to choose file</p>
</div>
</div>
.
.
.
</form>
I built a direcvtive to show thee file name dorring the upload:
/*get and shows the file name*/
app.directive('fdInput', function($timeout){
return {
scope: {
fileNames: '='
},
link:function(scope, element, attrs) {
$timeout(element.on('change', function(evt) {
var files = evt.target.files;
scope.fileNames = files[0].name;
scope.$apply();
}),0);
}
}
});
and this is the upload file controller:
app.controller('uploadDownloadsController',function($scope,$modalInstance,$timeout){
$scope.fileNames = '';
$scope.choose = function(){
$('#uploadDownloads').trigger('click');
};
$scope.add = function(valid){
if(valid){
$scope.data = 'none';
$scope.notPass = false;
/*this catches the file*/
var fileInput = document.getElementById('uploadDownloads');
var file = fileInput.files[0];
/* to send the file and the other inputs about it, need to use formData type*/
var formData = new FormData();
formData.append('file', file);
formData.append('fileName', $scope.fileName);
formData.append('fileExplain', $scope.fileExplain);
console.log(formData);
$modalInstance.close(formData);
} else {
$scope.notPass = true;
}
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});

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!

Resources