I just starting in AngularJs and Firebase. I am creating a todo list app.
In my app I have an html form like so :
<form name="frm" ng-submit="addTodo()" id="form-border">
<div class="form-inline">
<input type="text" class="form-control" name="newtodo" ng-model="newtodo" required="" id="inputform" />
<button class="btn btn-success" ng-disabled="frm.$invalid">Go</button>
<button class="btn btn-danger" ng-click="clearCompleted(todo)">Clear Completed</button>
</div> <!-- end form group -->
</form>
Below the form are the actual "todo" tasks in an html unordered list, added through with the form above.
code example:
<li ng-repeat="todo in todos" ng-mouseenter="hover = true" ng-mouseleave="hover = false" class="list-group-item" ng-class="inactive" >
<input type="checkbox" ng-model="todo.done" ng-click="clickDone(todo)"/>
<span ng-class="{'done':todo.done}" id="donetask">{{todo.title}}</span><!-- add line-through when task is done-->
<ng-include ng-class="{'hiRank-off': !hover}" src="'rankbutton.html'"></ng-include><!-- ng-include rankbutton-->
</li>
My app.js is storing this data with Firebase:
var myData = new Firebase("https://firebaseio-demo.com/ToDos");
and
$scope.todos.$add({'title':$scope.newtodo,'done':false, 'timetag': datecreated}); //push to Array
$scope.newtodo = '';
I am marking my tasks completed clickDone(todo) which grabs variable 'todo' from my ng-repeat. Like so:
$scope.clickDone = function(todo){
$scope.todos.$save(todo); //saves todo state when is checked
};
My dilemma is I am trying to delete an object with my ng-click="clearCompleted(todo)", or in other words marked as complete.
which can be found in the first code block
But I don't think clearCompleted()function is in the ng-repeat="todo in todos" scope, so I'm having some troubles deleting objects with this function.
I am trying this to delete with no success and errors
TypeError: Cannot read property 'done' of undefined
$scope.clearCompleted = function($scope.todos){
$scope.todos.$remove($scope.todo.done);
};
I just figured it out!! I had to run forEach( ) method to look in $scope.todos and check if todo.done evaluated to true.
$scope.clearCompleted = function(){ $scope.todos.forEach(function(todo){ if(todo.done){ $scope.todos.$remove(todo); } }); };
Related
With a play view template I know I can convert a Scala List into a javascript Array e.g. for example.scala.html:
#(list: List[Any])
#import play.api.libs.json.Json
<script type="text/javascript">
$(document).ready(function () {
var jsArr = #Json.toJson(list);
console.log(jsArr);
});
</script>
but how does one go back the other way, converting a javascript array into a scala list to pass on to a controller?
I have template code (test.scala.html) like this:
#(selected: List[String])
#main("Test Scripts Page") {
<div class="page-header page-heading">
<h1 class="pull-left">Test Scripts Page</h1>
#helper.form(action = helper.CSRF(routes.DoSomething.create(selected))) {
<input type="submit" class="btn btn-primary pull-right" value="Done >"> }
<div class="clearfix"></div>
<p class="lead text-left">Choose Buttons</p>
</div>
#for(index <- 0 to 3) {
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary"><input type="checkbox" name="options" id="option-#index" aria-pressed="false" autocomplete="off" checked>option #index</label>
</div> <!-- buttons --> }
<input type="text" id="buttonvalue"/>
<script>
$(window).unload(function() {
var jsArray = []
$('.btn-group checkbox:selected').each(function() {
jsArray.push($(this).attr("id"));
});
selected = Json.fromJson(jsArray, String);
$("#buttonvalue").val(selected.text());
});
</script>
}
Which doesn't seem to be working... only returns an empty list [] to my DoSomething(List) controller... basically I'm trying to let the user set the state of some widgets (in my case a bootstrap button-grp, with the ids of the buttons being object ids of static reference data in my database) and then read that selection back into my DoSomething controller as a List of ids when they hit a "done" button. Can anyone offer some advice on what I've missed here or a better way to handle this situation?
When you load a page, this happens:
Your browser asks the server for a HTML page.
Your scala code is run on the server and generates a HTML page with some javascript on it.
The server sends the HTML page to the browser. The javascript code then runs in the browser and therefore can't talk to the server code (Scala).
To send data back to the server you can make an HTTP call e.g. to a REST endpoint that your server offers.
Ok. I have a solution for this.
My view template looks like this, with the Bootstrap button-grp tagged with "myButtons" (note: if you insert anything between the btn-group div and the label class buttons, JQuery doesn't seem to pick up the checked options), and an script with ajax call bound to the submitButton.
Test Scripts Page
">
Choose Buttons
<div id="myButtons" class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="checkbox" name="options" id="option1" autocomplete="off" checked> Box 1 (preselected)
</label>
<label class="btn btn-primary">
<input type="checkbox" name="options" id="option2" autocomplete="off"> Box 2
</label>
<label class="btn btn-primary">
<input type="checkbox" name="options" id="option3" autocomplete="off"> Box 3
</label>
</div>
<script>
$('#submitButton').click(function(e) {
var selected = $( "#myButtons :checked" ).map(function() {
return this.id;
}).get().join();
var selections = JSON.stringify({ 'selected' : selected });
$.ajax({
type : "POST",
dataType: 'json',
data: selections,
contentType: "application/json; charset=utf-8",
url : "#routes.Application.getSelection()",
success: function(data) {
console.log(data);
}
});
return false;
});
</script>
my controller then picks up the selection via the AJAX post thus:
public static Result getSelection()
{
JsonNode json = request().body().asJson();
if( json == null)
{
Logger.info("Expecting JSON!");
return badRequest("Expecting Json data!");
}
else
{
String selection = json.findPath("selected").textValue();
if (selection == null)
{
Logger.info("Missing Parameter: selected");
return badRequest("Missing Parameter: selected");
}
else
{
Logger.info("selection = " + selection);
String[] ids = selection.split(",");
}
}
return ok(modaltest.render());
}
in my application code, those selections map to object ids in a model stored in my database, and then can be re-used in a subsequent request.
The only issue now is that the final return Request of my getSelection() controller (i.e. another GET to render a new page with a form) doesn't get invoked. No idea why yet. Probably something to do with the Ajax POST.
I'm just starting out with Angular.
I've written some code that downloads a JSON array configuredAPIs and displays each object within it, <div ng-repeat="capi in configuredAPIs">. For each of these, there's another directive to list the items from an array of strings, <tr ng-repeat="eurl in capi.externalURLs">
Underneath there's a text box to add a new string to this array, which I've bound to a $scope variable called url.
When I click the 'add' button, everything works - the new string is added to the array, a new row appears in the table.. ..but it only works once. Subsequent clicks on the 'add' button add empty strings to the array (and thus empty text boxes).
What have I done wrong?
index.html
<div ng-app="testApp" ng-controller="testCtrl">
<div ng-repeat="capi in configuredAPIs">
<h1>Configured API</h1>
<p>
Name:
{{ capi.name }}
</p>
<h2>External URLs</h2>
<form ng-submit="addExternalURL(capi)">
<table>
<!-- A row in the table for each string in the array -->
<tr ng-repeat="eurl in capi.externalURLs">
<td>
<input type="text" ng-model="eurl" />
</td>
</tr>
<!-- Final table row to add a new string to the array -->
<tr>
<td>
<input type="text" ng-model="url" placeholder="Enter a new external URL">
<input class="btn-primary" type="submit" value="add">
</td>
</tr>
</table>
</form>
</div>
</div>
controller.js
var app = angular.module('testApp', []);
app.controller('testCtrl', function ($scope, $http) {
$scope.url = 'new url';
$http.get("/api/configuredapis?orgid=2")
.success(function (response) { $scope.configuredAPIs = response; });
$scope.addExternalURL = function ($capi) {
$capi.externalURLs.push($scope.url);
$scope.url = '';
};
});
It is because AngularJS does not watch and update primitives (e.g. strings, numbers, booleans) the way one obviously thinks it does.
So instead you bind objects with values to the scope or use a function which returns the primitive value.
See:
https://github.com/angular/angular.js/wiki/Understanding-Scopes
http://www.codelord.net/2014/05/10/understanding-angulars-magic-dont-bind-to-primitives/
Example for using an object (at controller):
$scope.primitives = {
url : 'foo://'
}
And within the template:
<input type="text" ng-model="primitives.url">
So what happens in your example is that once you set it to '' the changes to the model within the template are not recognized anymore.
I have a form which has 10 checkboxes. By default angular js triggers on individual checkbox. I want to grab all selected check box values on submit action only. Here is my code...
<form name="thisform" novalidate data-ng-submit="booking()">
<div ng-repeat="item in items" class="standard" flex="50">
<label>
<input type="checkbox" ng-model="typeValues[item._id]" value="{{item._id}}"/>
{{ item.Service_Categories}}
</label>
</div>
<input type="submit" name="submit" value="submit"/>
</form>
$scope.check= function() {
//console.log("a");
$http.get('XYZ.com').success(function(data, status,response) {
$scope.items=data;
});
$scope.booking=function(){
$scope.typeValues = [];
console.log($scope.typeValues);
}
I am getting empty array.
Can somebody tell how to grab all selected checkbox values only on submit event.
<div ng-repeat="item in items">
<input type="checkbox" ng-model="item.SELECTED" ng-true-value="Y" ng-false-value="N"/>
</div>
<input type="submit" name="submit" value="submit" ng-click="check(items)"/>
$scope.check= function(data) {
var arr = [];
for(var i in data){
if(data[i].SELECTED=='Y'){
arr.push(data[i].id);
}
}
console.log(arr);
// Do more stuffs here
}
Can I suggest reading the answer I posted yesterday to a similar StackOverflow question..
AngularJS with checkboxes
This displayed a few checkboxes, then bound them to an array, so we would always know which of the boxes were currently checked.
And yes, you could ignore the contents of this bound variable until the submit button was pressed, if you wanted to.
As per your code all the checkboxes values will be available in the typeValues array. You can use something like this in your submit function:
$scope.typeValues
If you want to access the value of 3rd checkbox then you need to do this:
var third = $scope.typeValues[2];
Declare your ng-model as array in controller, like
$scope.typeValues = [];
And in your template, please use
ng-model="typeValues[item._id]"
And in your controller, you will get this model array values in terms of 0 and 1. You can iterate over there.
I am new to Angularjs and facing one problem.
The requirement is little bit unique in itself, Here is the description:
I have two inputs, two dropdown and two Get buttons and once i enter one url in first input field and click on Get button, it will bind all the "key" not values to dropdown using "getApiResults" method in the controller but when i add other url in the second input field and click on Get button it will fetch all the keys from second api and bind the dropdown BUT the problem is it also bind the first dropdown again with second api results because of the fact that we are updating the "fieldnames". I don't know how to handle this problem.
Please help.. Here is the complete code:
<html lang="en">
<div ng-controller="HelloController">
<div>
<input ng-model="url1" style="width:400px" />
<button class="btn btn-danger" data-ng-click="getApiResults(url1)">
Get
</button>
<select class="form-control" ng-init="getApiResults(url1)"
data-ng-options="key as key for (key,value) in fieldnames[0]"
ng-model="selected"></select>
</div>
<br />
<br/>
<div>
<input ng-model="url" style="width:400px" />
<button class="btn btn-danger" data-ng-click="getApiResults(url)">
Get
</button>
<select class="form-control" ng-init="getApiResults(url)"
data-ng-options="key as key for (key,value) in fieldnames[0]"
ng-model="selected1"></select>
</div>
</div>
<script>
angular.module("myapp", [])
.controller("HelloController", function ($scope, $http) {
$scope.getApiResults = function (apiURL) {
$scope.fieldnames = [];
var serviceurl = apiURL;
$http.get(serviceurl).success(function (data) {
$scope.fieldnames = data;
});
};
});
</script>
They are both pointing to the same scope variable. You can make a small change to you getApiResults function:
$scope.getApiResults = function (dropdown, apiURL) {
$scope.fieldnames = [];
var serviceurl = apiURL;
$http.get(serviceurl).success(function (data) {
$scope.fieldnames[dropdown] = data;
});
And then on the html:
<button class="btn btn-danger" data-ng-click="getApiResults('dropdown1',url1)">
Get
</button>
<select class="form-control" ng-init="getApiResults('dropdown1',url1)"
data-ng-options="key as key for (key,value) in fieldnames['dropdown1']"
ng-model="selected"></select>
I'm trying to render a validation summary on a page using AngularJS. Here's what I have so far:
<div ng-app>
<div ng-controller="ctrl">
<form name="userForm">
<fieldset>
<legend>User Info</legend>
<p><label>Name: <input type="text" required ng-maxlength="15" name="name" ng-model="name" /></label></p>
<p><label>Age: <input type="number" required name="age" ng-model="age" /></label></p>
<p><label>Favorite Color: <input type="text" required name="favColor" ng-model="favColor" /></label></p>
<p><input type="button" value="Submit" ng-click="submitForm()" /></p>
</fieldset>
</form>
<div id="validationSummary" ng-show="hasValidationErrors()">
<ul>
<li ng-repeat="error in validationErrors">{{ error }}</li>
</ul>
</div>
</div>
</div>
In my controller, I'm creating an array with all of the errors.
function ctrl($scope) {
$scope.hasValidationErrors = function () {
return $scope.validationErrors && $scope.validationErrors.length > 0;
};
$scope.submitForm = function() {
$scope.validationErrors = [];
for (var property in $scope.userForm) {
if ($scope.userForm.hasOwnProperty(property) && $scope.userForm[property].$invalid) {
$scope.validationErrors.push($scope.userForm[property].$name);
}
}
}
}
The thing I can't figure out is: how can I get more than just the name of each field that is invalid? I've noticed that there is also an $error property on each field. Outputting this instead of $name gives me the following:
{"required":true,"maxlength":false}
{"required":true,"number":false}
{"required":true}
So I can get the field name, and I can get an object that describes what is wrong with that particular field. How can I define an error message, so that if a field is required it will output "{name} is required"? It seems like this could be a data- attribute on the input element itself, although I don't know how I would access that attribute.
Of course, it's also possible that I'm making things entirely too difficult on myself. Is there a better way to approach this while staying in the "AngularJS" world?
Here's a link to the jsFiddle I've been working on.
A far easier and cleaner way is demonstrated here
Simply put (where form1 is your form name attribute):
<ul>
<li ng-repeat="(key, errors) in form1.$error track by $index"> <strong>{{ key }}</strong> errors
<ul>
<li ng-repeat="e in errors">{{ e.$name }} has an error: <strong>{{ key }}</strong>.</li>
</ul>
</li>
</ul>
A totally dynamic validation summary based on AngularJS 1.5.7 with ngMessages using field names that the user recognizes
A template with error messages:
<script type="text/ng-template" id="error-messages">
<span ng-message="required">This field is required.</span>
<span ng-message="email">Please enter a valid email.</span>
</script>
Display of the error summary (here for a form named "candidateForm"):
<div data-ng-if="candidateForm.$submitted && candidateForm.$invalid">
Please correct these fields and then try to send again:
<ul>
<li data-ng-repeat="field in candidateForm" data-ng-if="candidateForm[field.$name].$invalid">
<div>
{{ getValFieldName(field) }}
<span data-ng-messages="candidateForm[field.$name].$error" role="alert">
<span data-ng-messages-include="error-messages"></span>
</span>
</div>
</li>
</ul>
</div>
A helper function to get the name of the label associated with the input field (instead of displaying input field names or "internal ID codes" to users):
$scope.getValFieldName = function (field) {
return $("label[for=" + field.$name + "]").text(); // to get label associated with input field
// return $("#" + field.$name).attr("placeholder"); // to get placeholder of input field
};
You can reuse this set of standard error messages on multiple forms, ngMessages ensure only one error displayed per field, and looks like the fields are listed in the order they appear in the HTML.
Should probably be made into a directive instead of the jQuery-style helper function, and might even want to add a click-handler on each error message to scroll to the input field with the error. Maybe another will run with that idea?
Use below line to get values of every text box
var value = $scope.userForm[property].$name;
var vl =$('*[name="' + value + '"]').data('required-message')
$scope.validationErrors.push(vl);