AngularJS display alert depending on input value - javascript

I am coding a CRUD application in Angular and Web API.
In the create/edit form (same template), I need to display an error message if 2 input fields don't have the same number of comma ','.
I found a way to make it work but I don't like it, I think it needs to be "angularized" but I don't know how.
Controller:
$scope.isColumnCountOk = true;
$scope.checkColumnCountOk = function () { $scope.isColumnCountOk = AdminUtils.isColumnCountOk($scope.item.columnSqlNames, $scope.item.columnTitles) };
Template:
<input type="text" class="form-control" ng-model="item.columnTitles" placeholder="Report Column 1,Report Column 2,Report Column 3,..." ng-blur="checkColumnCountOk()" required />
<div ng-hide="isColumnCountOk">
<br />
<div class="alert alert-danger" ><strong>Warning. </strong>Mismatch between column numbers</div>
</div>
I would like to get rid of the $scope.isColumnCountOk and have the function called directly from the template, without storing the return value in the scope.
Any advice?
Bruno

I think both of these ways should work...
$scope.isColumnCountOk = function () {
return AdminUtils.isColumnCountOk($scope.item.columnSqlNames, $scope.item.columnTitles);
};
<div ng-hide="isColumnCountOk()">
...
</div>
Or
$scope.isColumnCountOk = AdminUtils.isColumnCountOk;
<div ng-hide="isColumnCountOk(item.columnSqlNames, item.columnTitles)">
...
</div>

Related

angular-tags: Reset the tags input value

index.html
<div class="modal-header" >
<button type="button" class="close" ng-click = "submit(information.add, information.subject, information.emailContent); close()">×</button>
<h3>Compose Email</h3>
</div>
<div class="modal-body">
<form name = "form.email">
<tags options="{addable: true}" typeahead-options="typeaheadOpts" data-model="information.add" data-src="toPerson as toPerson for toPerson in to"></tags>
<input type="text" placeholder="Subject" style="width:95%;" data-ng-model = "information.subject"><br />
<textarea style="width:95%;" rows="10" data-ng-model = "information.emailContent"></textarea>
</form>
</div>
emailViewController.js
$scope.information = {
add: [],
subject: [],
emailContent: []
};
$scope.clear = function() {
if ($scope.information.add !== "") {
$scope.information = null;
}
};
I am setting the value of $scope.information to null. After doing this, the input box value bound to information.subject and the textarea value bound to information.emailContent are reset. However, the tags input value bound to information.add does not reset. Does anyone know why this is being caused.
I think $scope.remove() in the angular-tags widget should be used to remove the tag. I am not sure how to implement it though. Angular-tags source code can be found here - https://github.com/boneskull/angular-tags/blob/master/src/tags.js
Here is a plunker - http://plnkr.co/edit/PaG1k5N37BTOflObnN7K?p=preview
Attempt 1
This is a plunker of what I have tried so far - http://plnkr.co/edit/jjE2bU8zkkyw36rtAymL?p=preview . I am redefining the value of $scope.info to null in a function wrapped inside $timeout. I thought maybe the changes I made to the $scope are not being applied to the view, so I tried to wrap it in a $timeout. Doing so did not fix the problem though.
This code $scope.information = null; is supposed to nuke all your information and clear the entire thing? This only sets the reference to the object containing the arrays to null. The arrays are still there and still referenced by your widget I expect - (I'm not sure how the library you are using for your tags is implemented)
The below code actually empties the arrays:
$scope.information.add.length = 0;
$scope.information.subject.length = 0;
$scope.information.emailContent.length = 0;

AngularJS Filter, set class of of label and input field with validation

I have an Angular app with a list of F1 drivers. I want to put a filter on the table, so I can get drivers by their first or by their last name.
To make this I use following design:
Normally the label and the line of the input are black. I want to check if the input value only is a String value (a-zA-Z). I use following code in my partial view:
<div class="form-group col-xs-5 col-md-3">
<label class="control-label" for="inputError">input must be [a-zA-Z]</label>
<div class="form-control-wrapper">
<input ng-model="nameFilter" type="text" name="nameFilter" class="form-control empty" placeholder="Search Driver name...">
<span class="material-input"></span>
</div>
</div>
This input value is bound with following filter (declared in my controller.js)
$scope.searchFilter = function (driver) {
var re = new RegExp($scope.nameFilter, 'i');
if(! (/[^a-zA-Z]+/).test($scope.nameFilter)){
$scope.nameFilter.class ='control-label';
}
return !$scope.nameFilter || re.test(driver.Driver.givenName) || re.test(driver.Driver.familyName);
};
But this doesn't work.. What am I missing?
Regex
Your Regular expression is wrong, check out its validity here
change it from
/[^a-zA-Z]+/
to
/^[A-Za-z]+$/

AngularJS - Find all ngModel in the current scope

I have a HTML template like this:
<div ng-controller="MyCtrl">
<input ng-model="model.name" /> {{model.addr}}
<button ng-click="detect()">detect</button>
</div>
And this is the controller:
function MyCtrl($scope) {
$scope.detect = function() {
var fields = []; //['model.name', 'model.addr']
//call server with selected fields
}
}
The template can be customized by user and generated dynamically, not static template. I want to optimize the data model returned from server, only return values for needed fields in the template. The idea is I want to get all the ng-model fields from template and pass them to the server. The returned data will contain only values for these fields, instead of whole data model, for example:
{
name: 'Superhero',
addr: 'Mars'
}
If I change the template like this (remove model.addr):
<div ng-controller="MyCtrl">
<input ng-model="model.name" />
<button ng-click="detect()">detect</button>
</div>
The fields array should be ['model.name'] and the returned data from the server should be:
{
name: 'Superhero'
}
There are any ways to get all ng-model fields in the scope?
Thanks!
You can do 1 thing, wherever you are using ng-modal, take an object modal and assign values by using dot(.).
Suppose
<div ng-controller="MyCtrl">
<input ng-model="model.name1" />
<input ng-model="model.name2" />
<input ng-model="model.name3" />
<button ng-click="detect()">detect</button>
So you can get model in scope hence all the attributes of scope.

AngularJS does not send hidden field value

For a specific use case I have to submit a single form the "old way". Means, I use a form with action="". The response is streamed, so I am not reloading the page. I am completely aware that a typical AngularJS app would not submit a form that way, but so far I have no other choice.
That said, i tried to populate some hidden fields from Angular:
<input type="hidden" name="someData" ng-model="data" /> {{data}}
Please note, the correct value in data is shown.
The form looks like a standard form:
<form id="aaa" name="aaa" action="/reports/aaa.html" method="post">
...
<input type="submit" value="Export" />
</form>
If I hit submit, no value is sent to the server. If I change the input field to type "text" it works as expected. My assumption is the hidden field is not really populated, while the text field actually is shown due two-way-binding.
Any ideas how I can submit a hidden field populated by AngularJS?
You cannot use double binding with hidden field.
The solution is to use brackets :
<input type="hidden" name="someData" value="{{data}}" /> {{data}}
EDIT : See this thread on github : https://github.com/angular/angular.js/pull/2574
EDIT:
Since Angular 1.2, you can use 'ng-value' directive to bind an expression to the value attribute of input. This directive should be used with input radio or checkbox but works well with hidden input.
Here is the solution using ng-value:
<input type="hidden" name="someData" ng-value="data" />
Here is a fiddle using ng-value with an hidden input: http://jsfiddle.net/6SD9N
You can always use a type=text and display:none; since Angular ignores hidden elements. As OP says, normally you wouldn't do this, but this seems like a special case.
<input type="text" name="someData" ng-model="data" style="display: none;"/>
In the controller:
$scope.entityId = $routeParams.entityId;
In the view:
<input type="hidden" name="entityId" ng-model="entity.entityId" ng-init="entity.entityId = entityId" />
I've found a nice solution written by Mike on sapiensworks. It is as simple as using a directive that watches for changes on your model:
.directive('ngUpdateHidden',function() {
return function(scope, el, attr) {
var model = attr['ngModel'];
scope.$watch(model, function(nv) {
el.val(nv);
});
};
})
and then bind your input:
<input type="hidden" name="item.Name" ng-model="item.Name" ng-update-hidden />
But the solution provided by tymeJV could be better as input hidden doesn't fire change event in javascript as yycorman told on this post, so when changing the value through a jQuery plugin will still work.
Edit
I've changed the directive to apply the a new value back to the model when change event is triggered, so it will work as an input text.
.directive('ngUpdateHidden', function () {
return {
restrict: 'AE', //attribute or element
scope: {},
replace: true,
require: 'ngModel',
link: function ($scope, elem, attr, ngModel) {
$scope.$watch(ngModel, function (nv) {
elem.val(nv);
});
elem.change(function () { //bind the change event to hidden input
$scope.$apply(function () {
ngModel.$setViewValue( elem.val());
});
});
}
};
})
so when you trigger $("#yourInputHidden").trigger('change') event with jQuery, it will update the binded model as well.
Found a strange behaviour about this hidden value () and we can't make it to work.
After playing around we found the best way is just defined the value in controller itself after the form scope.
.controller('AddController', [$scope, $http, $state, $stateParams, function($scope, $http, $state, $stateParams) {
$scope.routineForm = {};
$scope.routineForm.hiddenfield1 = "whatever_value_you_pass_on";
$scope.sendData = function {
// JSON http post action to API
}
}])
I achieved this via -
<p style="display:none">{{user.role="store_user"}}</p>
update #tymeJV 's answer
eg:
<div style="display: none">
<input type="text" name='price' ng-model="price" ng-init="price = <%= #product.price.to_s %>" >
</div>
I had facing the same problem,
I really need to send a key from my jsp to java script,
It spend around 4h or more of my day to solve it.
I include this tag on my JavaScript/JSP:
$scope.sucessMessage = function (){
var message = ($scope.messages.sucess).format($scope.portfolio.name,$scope.portfolio.id);
$scope.inforMessage = message;
alert(message);
}
String.prototype.format = function() {
var formatted = this;
for( var arg in arguments ) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
<!-- Messages definition -->
<input type="hidden" name="sucess" ng-init="messages.sucess='<fmt:message key='portfolio.create.sucessMessage' />'" >
<!-- Message showed affter insert -->
<div class="alert alert-info" ng-show="(inforMessage.length > 0)">
{{inforMessage}}
</div>
<!-- properties
portfolio.create.sucessMessage=Portf\u00f3lio {0} criado com sucesso! ID={1}. -->
The result was:
Portfólio 1 criado com sucesso! ID=3.
Best Regards
Just in case someone still struggles with this, I had similar problem when trying to keep track of user session/userid on multipage form
Ive fixed that by adding
.when("/q2/:uid" in the routing:
.when("/q2/:uid", {
templateUrl: "partials/q2.html",
controller: 'formController',
paramExample: uid
})
And added this as a hidden field to pass params between webform pages
<< input type="hidden" required ng-model="formData.userid" ng-init="formData.userid=uid" />
Im new to Angular so not sure its the best possible solution but it seems to work ok for me now
Directly assign the value to model in data-ng-value attribute.
Since Angular interpreter doesn't recognize hidden fields as part of ngModel.
<input type="hidden" name="pfuserid" data-ng-value="newPortfolio.UserId = data.Id"/>
I use a classical javascript to set value to hidden input
$scope.SetPersonValue = function (PersonValue)
{
document.getElementById('TypeOfPerson').value = PersonValue;
if (PersonValue != 'person')
{
document.getElementById('Discount').checked = false;
$scope.isCollapsed = true;
}
else
{
$scope.isCollapsed = false;
}
}
Below Code will work for this IFF it in the same order as its mentionened
make sure you order is type then name, ng-model ng-init, value. thats It.
Here I would like to share my working code :
<input type="text" name="someData" ng-model="data" ng-init="data=2" style="display: none;"/>
OR
<input type="hidden" name="someData" ng-model="data" ng-init="data=2"/>
OR
<input type="hidden" name="someData" ng-init="data=2"/>

Knockout .js and changing values on click

Simplified code below. I have another build w/ajax calls that I know are working b/c I can see them hit the server. But I cannot get the stuff to render the changes back to the UI.
.html:
<div id="LoginPage" data-title="LoginPage" data-role="page" data-theme="a">
<div data-role="content" class="minimalPaddingContent">
<div class="divDivider"></div>
<h3>REACH Energy Audit Login</h3>
<input type="text" placeholder="User Name" id="userName" data-bind="value: successOrFailureSw"/>
<input type="password" placeholder="Password" id="password"/>
Sign In
<span data-bind="text: successOrFailureSw"></span>
</div>
.js:
var LoginViewModel = function (commonName, successOrFailureSw) {
var self = this;
self.commonName = ko.observable(commonName);
self.successOrFailureSw = ko.observable(successOrFailureSw);
self.changeValue = function(){
console.log("changed!");
self.successOrFailureSw = "new value!";
}
};
ko.applyBindings(new LoginViewModel("", "super fail"));
I am pretty sure my mappings are correct on the .html b/c the original value will render as super fail, and if I change the value in the text box that maps to "successOrFailureSw", I get the updated value in the span tag, but I cannot get a change of effect at click time for the login button.
I know that I am missing something so simple, so I apologize in advance.
Thanks!
brian
You assign value to the observable in wrong way. Each obserbable is a function so you should call it using () modify your changeValue function to the following:
self.changeValue = function(){
console.log("changed!");
self.successOrFailureSw("new value!");
}
You should set the value like this:
self.successOrFailureSw('new value!');
successOrFailureSw is not a string. That's why you need to set it in the same fashion that you did earlier in your code.
Try this :
self.successOrFailureSw("new value!")

Categories