AngularJS binding datatimepicker selected value to ng-model - angularjs

I have a newbie AngularJS question - I am using a datetimepicker library and I'm having a hard time getting the date selected to bind to my model... I saw some posts talking about not being able to access the datetimepicker model directly, but in my case I find that if I just manually TYPE IN a text value in my date input box, it binds! If I select a date with the chooser, I get the dreaded 'undefined' :(... help?
HTML markup:
<div class="col-md-2">
<div name="fromDateTime" class="input-group date" id="datetimepickerFrom">
<input class="form-control" type="text" name="fromDateTime" ng-model="formEntries.fromDateTime"/>
<span class="input-group-addon" data-ng-click="pickFromDateTime()"><span class="glyphicon glyphicon-calendar" id="calIconFrom"></span></span>
</div>
</div>
<div class="col-md-2">
<div name="toDateTime" class="input-group date" id="datetimepickerTo">
<input class="form-control" type="text" name="toDateTime" ng-model="formEntries.toDateTime"/>
<span class="input-group-addon" data-ng-click="pickToDateTime()"><span class="glyphicon glyphicon-calendar"></span></span>
</div>
</div>
Controller:
$scope.pickFromDateTime = function () {
$("#datetimepickerFrom").datetimepicker();
$("#datetimepickerFrom").datetimepicker().change(function() {
$(this).data("DateTimePicker").hide();
console.log($(this).data("DateTimePicker").getDate());
});
}
$scope.pickToDateTime = function () {
$("#datetimepickerTo").datetimepicker();
$("#datetimepickerTo").datetimepicker().change(function() {
$(this).data("DateTimePicker").hide();
console.log($(this).data("DateTimePicker").getDate());
});
}
$scope.getData = function() {
console.log($scope.formEntries.fromDateTime);
console.log($scope.formEntries.toDateTime);
}

Never ever ever write DOM or jQuery code in your controller. It will never work properly. You must create a directive to do this. The directive will listen to events from whatever library you're using and update your model. Here is an example of a directive that happens to work with the datepicker. This should get you on the right track.

Related

Get pristine value in Angular controller

I need to be able to see in the Angular controller if the datepicker is pristine or not. Tried all sorts of things including sending the pristine value in a method but cannot get this value. Below is the view code:
<form name="myForm">
<!-- Datepicker From -->
<div class="small-6 medium-5 large-2 columns" ng-if="vm.subViewActive">
<div class="input-group">
<input name="valuationDatePickerFrom" ng-model="name" type="text" class="datepicker" id="valuationDatePickerFrom" placeholder="DD/MM/YYYY" pikaday="vm.datePickerFrom" on-select="vm.selectStartDate(pikaday)" year-range="{{ vm.yearRange }}" >
<div class="input-group-addon">
<label for="valuationDatePickerFrom" class="postfix">
<i class="fa fa-calendar"></i> From
</label>
</div>
</div>
</div>
</form>
and then I also tried :
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
in my controller but cannot get the pristine value. Read lots of posts here but mainly to do with CSS classes and front-end control or setting the pristine state from the backend not getting or checking the pristine state.
Thanks anybody that can help.
You are using:
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
but your form's name is not myForm.
Change <input name="name"... <input name="valuationDatePickerFrom"...
Then you can use:
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
Also, the controller is getting called before the view is created, so no myForm exists at the time the controller runs. Try adding a $timeout like so:
$timeout(function() {
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
}, 100);
plunkr
The above solution only works on page load, but you need to know this value when the page is being used. Instead pass the value to the controller when an action happens:
<form name="myForm">
<input type="text" name="valuationDatePickerFrom" ng-model="valuationDatePicker" ng-blur="alerty(myForm.$pristine)">
</form>
.controller('MainController', function($scope) {
$scope.alerty = function(isPristine){
alert('isPristine: ' + isPristine);
};
https://plnkr.co/edit/f0EWvYmoXCn8UOH3QCfE?p=preview

Checkbox not sending false value

I have a rails application which use AngularJS and I have a problem with a form, the problem is that I want to use a checkbox to send values true or false, but it only send true if it's checked and false if it's checked and unchecked after that, but if the user doesn't touch the checkbox, then it's not even sent as parameter.
<div class="checkbox">
<label>
<input type="checkbox" ng-model="car"> Do you have a car?
</label>
</div>
What can I do to make it send false if it the user doesn't ever check it?
Edit: The entire form is this, BTW, the form it's about creating a Poll, the car thing was just an example...
<h1>Create Poll</h1>
<form ng-submit="addPoll()" style="margin-top:30px;">
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" ng-model="title"></input>
</div>
<div class="form-group">
<label>Description</label>
<textarea type="text" class="form-control" ng-model="description"></textarea>
</div>
<br>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="allow_anonymous_answer" ng-false-value="false"> Allow anonymous answers
</label>
</div>
<br>
<div class="form-group">
<label>Welcome message</label>
<textarea type="text" class="form-control" ng-model="initial_message"></textarea>
</div>
<div class="form-group">
<label>Outgoing Message</label>
<textarea type="text" class="form-control" ng-model="final_message"></textarea>
</div>
<button type="submit" class="btn btn-primary" style="float: right;">Continue</button>
</form>
When you hit Continue I make HTTP POST request with Restangular to create a Poll, but the problem is that when I don't touch the checkbox this is what I see in the log of Rails...
Started POST "/polls.json" for 127.0.0.1 at 2016-01-26 14:05:57 -0300
Processing by PollsController#create as JSON
Parameters: {"title"=>"asddddddddddddddda", "description"=>"aaaaaaaaaaaaaaaaaaaaa", "initial_message"=>"asdasdddddddddd", "final_message"=>"aaaaaaaaaaaaaaaaaaad", "poll"=>{"title"=>"asddddddddddddddda", "description"=>"aaaaaaaaaaaaaaaaaaaaa", "initial_message"=>"asdasdddddddddd", "final_message"=>"aaaaaaaaaaaaaaaaaaad"}}
Note that the parameter allow_anonymous_answer doesn't even appear, if I check the checkbox then I can see that the parameter is set as true, if I check it and then uncheck it, then it's set as false, but the problem is when the user doesn't even touch this, when this happens then the parameter is not even shown...
Just in case you wanna see, this is the controller of AngularJS...
angular.module('myapp').controller('CreatePollCtrl', ['$scope', 'Restangular',
function($scope, Restangular) {
Restangular.setFullResponse(true);
$scope.addPoll = function() {
var poll = {title: $scope.title, description: $scope.description, allow_anonymous_answer: $scope.allow_anonymous_answer, initial_message: $scope.initial_message, final_message: $scope.final_message};
Restangular.all('polls').post(poll).then(function(response) {
});
};
}]);
I think you should put a variable in your controller to achieve the binding between your HTML component and your JS code.
I am currently developing an Angular app, and what i do is to initialize all the ng-model variables in the first lines of my controller, so why dont you give a try to this:
In your first controllers lines:
$scope.allow_anonymous_answer = false;
Did you take a look at angular docs: https://docs.angularjs.org/api/ng/input/input[checkbox]
You can explicitly state what value the checkbox should send when it is not selected using ng-false-value
Add an ng-click to that checkbox and update the model there. Works fine.
<div class="checkbox">
<label>
<input type="checkbox" ng-model="car" ng-click="updateCar(this)">Do you have a car?</input>
</label>
</div>
In your controller:
var updateCar = function(checkbox) {
if (checkbox.checked) {
car = false;
}
else {
car = true;
}
}
I solved it...
In the controller
if ($scope.allow_anonymous_answer == null)
$scope.allow_anonymous_answer = false

ng-models name collision inside ng-repeat

http://plnkr.co/edit/2UFfaG?p=preview
I used this sample code to build a simple app and I noticed that the edit function doesn't work when you are using ng-models that are repeated in a loop. I know this, because I tried using ng-models outside of the ng-repeat loop and it worked perfectly. So when you have two instances of ng-models with the same name, you get a blank data back when you try to get the values back from the view.
This is my view:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note.id)">Save</button>
</form>
</li>
</ul>
This is my edit method:
$scope.edit = function (id) {
var note = notesRef.child(id);
var newNote= {
name : $scope.name,
content : $scope.content
}
};
note.update(newNote);
};
When I refer to a ng-model inside of ng-repeat, I can only get the value null for some reason. I get the correct value when I refer to ng-models outside of the ng-repeat for some reason.
How do we solve this problem? What's the simplest solution?
The problem is that the item belongs to the scope of the repeat.
If you changed your ng-model to:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="note.name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="note.content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note)">Save</button>
</form>
</li>
</ul>
Where it's now note.name / note.content.
Then instead of padding the note.id to the edit button, you pass in the entire note i.e ng-click="edit(note)"
Then your controller will get passed the entire note.
$scope.edit = function (note) {
// send note to server via $http, changes to `note` are already made directly to the note itself
};
Hope that makes sense.
it should be like this. As we know ng-repeats directive create their own new scope.
bday.editing
<ul ng-repeat="bday in bdays">
<li>
<span ng-hide="bday.editing" ng-click="bday.editing = true">{{bday.name}} | {{bday.date}}</span>
<form ng-show="bday.editing" ng-submit="bday.editing = false">
<label>Name:</label>
<input type="text" **ng-model="bday.name"** placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" **ng-model="bday.date"** placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</li>
</ul>
and here what I understand from your question is that you want to edit only the item on which you have click. this is the solution for the same.
One more solution for the same problem is that create a new function that take one argument that is "bday". make edit true only for this item and set editing false for all others element. this solution is for that case if user doesn't submit the form and click on other item.

AngularJS : ng model not updating via date picker

I have a datetimepicker.
Overall, it works fine and updates the text box fine. However, when I place a ng-model onto the input field, nothing gets passed through to the binding at the bottom of the page.
Here!s the form I'm using :
<div class="form-group">
<div class='input-group date' id='datetimepicker3'>
<input type='text' ng-model="package.timeA" value="" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-time"></span>
</span>
</div>
</div>
This is my JS code :
$(function () {
$('#datetimepicker3').datetimepicker({
format: 'LT'
});
});
For the input box give some id or class name then initialize datepicker with that id or class
<input type='text' ng-model="package.timeA" value="" class="mydatePicker form-control" />
$('.mydatePicker ').datetimepicker();
It will work.
You can try to use $apply who allow to force reload of the variable and $setViewValue who allow to set the variable of the view.
add ng-change on your input tag and pass the date.
In your controller you can make a function like this:
$scope.onChange = function(package.timeA)
{
$scope.$apply(function (){
YourCtrl.$setViewValue(package.timeA)
}
}

How to add object properties from ng-checked items to my ng-model object

I have four input fields which I'm using to add properties to a single object using ng-model= model.propertyName. I have a series of check boxes that I'm creating with ng-repeat that I could not figure out how to add unique propertyNames for each ng-model as they were created with the ng-repeat. As a work-around(or maybe this is correct, I'm not sure) I was able to write a function to add the checked items to an array. I was then trying to use a for-loop to iterate over the array and add each selected propertyName(string) to the ng-model object as a new property using a ng-click to call the function.
As-is when I click the "Add Technician" button I get the following error output:
TypeError: Cannot read property 'selection' of undefined
at Scope.$scope.addTechnician (..../scripts/controllers.js:
This occurs because $scope is undefined inside the conditional of my for loop in the addTechnician function. I can't understand why because when I pass $scope to the addTechnician function it recognizes the newTech inside the for loop. When I don't pass $scope to the addTechnician function it says newTech is undefined with the following error:
TypeError: Cannot set property 'cert1' of undefined
at Scope.$scope.addTechnician(.../scripts/controllers)
I'm pretty sure this has something to do with the way ng-repeat creates a new scope, which prototypically inherits from the parent scope. But again, I'm not sure.
Here is my controller
use strict';
angular.module('Carrepair2.controllers', [])
.controller('SetupCtrl', function($scope) {
$scope.certifications = [
{'name':'Engine Repair'},
{'name':'A/T & Transaxle'},
{'name':'Manual Drive Train & Axles'},
{'name':'Suspension & Steering'},
{'name':'Brakes'},
{'name':'Electrical & Electronic Systems'},
{'name':'Heating & Air Conditioning'},
{'name':'Engine Performance'},
{'name':'Light Vehicle Diesel Engines'}
];
// selected certifications
$scope.selection = [];
$scope.toggleCert = function(name) {
var idx = $scope.selection.indexOf(name);
//is currently selected
if (idx > -1) {
$scope.selection.splice(idx, 1);
}
//is newly selected
else{
$scope.selection.push(name);
}
};
$scope.addTechnician = function($scope) {
for(var i=0; i < $scope.selection.length - 1; i++){
$scope.newTech['cert' + (i + 1).toString()] = $scope.selection[i].name;
}
};
})
Here is my template
<form class="col-md-6">
<div class="input_wrapper">
<input type="text" name="first-name" ng-model="newTech.firstName" required>
<label for="first-name">First Name</label>
</div>
<div class="input_wrapper">
<input type="text" name="last-name" ng-model="newTech.lastName" required>
<label for="last-name">Last Name</label>
</div>
<div class="input_wrapper">
<input type="email" name="email" ng-model="newTech.email" required>
<label for="email">Email</label>
</div>
<div class="input_wrapper">
<input type="tel" name="phone" ng-model="newTech.phone" required>
<label for="phone">Phone</label>
</div>
<h5>Check all held ASE certifications</h5>
<ul class="list">
<li class="item item-checkbox" ng-repeat="certification in certifications">
<label class="checkbox">
<input type="checkbox" value="{{certification.name}}" ng-checked="selection.indexOf(certification.name) > -1" ng-click="toggleCert(certification)">
</label>
{{certification.name}}
</li>
</ul>
<button class="button button-block" ng-click="addTechnician()">Add Technician</button>
</form>
Ideally after the "Add Technician" button is clicked I want to end up with an object, my newTech ng-model object, that has the input field data and the properties from the checked items. Here is a jsFiddle with simplified code replicating the problem
http://jsfiddle.net/aq93z/7/
I solved it. I had to format my loop using angular.forEach(values, function(value, index){here is the jsFiddle with the solution http://jsfiddle.net/aq93z/9/. If you look at the $scope.newTech object created in the console the checkbox selections are added as properties of the newTech ng-model object.

Resources