I am using AngularJS TimePicker (ui.bootstrap.timepicker). I would like to fire an event when the timepicker is changed. I looked for an ng-change attribute, but did not find one.
My purpose is that I would like to save the changes that are made to the model when the time is changed. Right now I've used ng-model to set the model, but I cannot figure out how to notify the controller so it can perform the save (the model is serialized to localstorage). I would like to avoid the use of a "Save" button if possible.
On a related note, I would also like to do the same thing for ui.bootstrap.datepicker.
You could use $scope.$watch to listen for changes to the timepicker (or datepicker) and call whatever is needed in the Controller. Here is a plunker that is based on the bootstrap example but alerts whenever the time is changed. You should be able to apply a similar logic for datepicker as well.
You can use in script
<input type='text' class="form-control" ng-model="callMeTime.startHour" ng-change= "addTime()" id='datetimepicker1' placeholder="End Time" onkeydown="return false"/>
<script>
<script type="text/javascript">
$(function() {
$('#datetimepicker1').datetimepicker({
format : "HH:mm",
});
$('#datetimepicker1').datetimepicker().on('dp.change', function (event) {
var user_time_picker1 = $("#datetimepicker1");
user_time_picker1.val(this.value);
user_time_picker1.trigger('input');
});
});
</script>
Related
What's a good way to debounce an ng-change event in angular? I know about the debounce available in ng-model options, but I want my model to update right away as its changed because the user has the option to submit this data, and I don't want any information to be missing from the post because the model was waiting for the debounce. I do want to add a debouncer on my ng-change event or the function it calls. The html for my element
<div ng-change="saveProg()" text-angular ng-model="message" required></div>
I'd like to debounce the saveProg function so it doesn't run once for every character typed, but once every second or so. My function looks like this
$scope.saveProg = function() {
ProgressService.saveProg({
topic: $scope.topic,
message: $scope.message
})
}
I don't use Angular regularly, but I understand that one of the key features is that when data is updated on a form element, it is automatically updated in the model.
If you are instead using a library like jQuery, you must manually attach an event to the form input that updates the model when it is changed, as in $('#myInput').on('change', updateModel);
Although the above handler will be fired when myInput is changed by the user, it will not be fired if myInput is changed by Javascript code such as $('#myInput').val('hello world');
My question is, how does Angular know when a form input is changed in Javascript code?
Angular applies a scope digest every time it's needed (by an Angular function) during which it checks the states of all the scope variables, including the models used, of course.
If you modify some of those variables manually, using JavaScript, jQuery, etc... Angular will not know that the changes have occured and you need to tell it so either by doing $scope.$apply() or by wrapping the code block in a $timeout callback (these are the most commonly used methods).
If you don't do it manually, you'd have to wait for some (if any) other Angular event to trigger the digest cycle, which is never good.
See this example, note how nothing happens when you just update the value, but you need to do it manually (ng-click does it) in order for DOM to update:
angular.module('app', [])
.controller('Ctrl', function($scope){
$scope.ourValue = 'Initial Value';
window.exposedFunc = function(v, digest) {
$scope.ourValue = v;
if (digest) {
$scope.$apply();
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
<button onclick="exposedFunc('First Button Value')">Update Value - No Digest</button>
<button onclick="exposedFunc('Second Button Value', true)">Update Value - Force Digest</button>
<button ng-click="">Force Digest only</button>
<p>{{ourValue}}</p>
</div>
Here's a super simple example of binding using keyup event. It should be enough to get you started on your projects:
var res = document.getElementById('r');
function handleChange(v) {
res.textContent = v;
}
<input onkeyup="handleChange(this.value)" type="text" value="Initial value" />
<p id="r">No binding yet</p>
I have used ng-paste for textarea while pasting the link in textarea, i am calling a custom function to store that value. Please refer following code
<textarea rows="1" ng-model="myObj.content"
ng-paste="getContent(myObj)">
</textarea>
$scope.getContent = function(a){
console.log(a.content);
}
But in console always I am getting undefined value. How can I get my object value?
Passing model to function does not really make sense since you have already specified ng-model, so it's value will be updated as user types something into the textbox. If you want to track changes you can setup a $watch for your model or specify a function using ng-change.
If you want to know what user pasted, then that's another story. Handling ng-paste can be tricky. To access the actual event, easiest is to include jQuery before angularjs and then do e.g. following:
HTML template
<textarea rows="3"
placeholder="copy/paste here..."
ng-init="content = null"
ng-model="content"
ng-paste="paste($event.originalEvent)">
</textarea>
Controller
$scope.paste = function (event) {
var item = event.clipboardData.items[0];
item.getAsString(function (data) {
console.log(data);
});
};
Related plunker here http://plnkr.co/edit/ea5y5j
Simply use $timeout to call your paste callback after the model has been updated.
$scope.getContent = function(a){
$timeout(function () {console.log(a.content)});
}
Question related to forms-angular project.
Preamble
The default formInput directive of forms-angular can be override by a custom directive by specifying the form.directive property in an extended mongoose model,
var CategorySchema = new Schema({
name: String,
});
var PlansSchema = new Schema({
categories: {
type: [CategorySchema],
form: {
directive: 'plan-categories'
}
}
});
The custom plan-categories directive has a template where fields of [CategorySchema] can be edited.
What is working
Let's start with a first simple template:
<div>
<div ng-repeat="category in record.categories">
<input ng-model="category.name" />
</div>
</div>
Forms-angular can successfully detect changes in these custom plan-categories directive input fields bound to data (injected scope.record). In particular when changing the user changes the value of the above input fields, the "Save" button of the page is enabled, allowing the Save operation.
The activation of the Save button thanks to the following comparison in parent formInput's BaseCtrl scope false === $scope[$scope.topLevelFormName].$pristine (see base.js).
Not working
Now, the Save button doesn't get enabled, when changing the category.name variable with an expression or a function called by ng-click, as below:
<div>
<div ng-repeat="category in record.categories">
<input ng-model="category.name" />
<button ng-click="category.name = 'Hello'">Edit</button>
</div>
</div>
On button click, the category.name variable seems to be correctly changed, since the value in the input is changed accordingly. Unfortunately, the Save button stays disabled.
Note: I also unsuccessfully tried to pass to ng-click a method (from the scope injected in the link method of the custom directive) and setting the category.name variable in a $timeout call.
I guess the ng-model directive of the input field calls parent's (multi-ancestor?) $setDirty() method.
Question
how do I magically get $setDirty() called by forms-angular in order to enable the "Save" button
If it is not possible:
how do I access BaseCtrl scope and call $setDirty() when changing the record.categories elements?
Offhand I cannot think of a magical solution, but the decidedly non-magical way is to depend on $data.baseScope (see https://github.com/forms-angular/forms-angular/blob/master/js/controllers/base.js#L12) which saves going through lots of $parents.
In my application i need a color picker with alpha transparency and after searching finally find angular-bootstrap-colorpicker so i try to use this.when normally i use this plugin it work and ng-model correctly but when i use this directive in angular-ui bootstrap , the plugin doesn't work and return undefined.
for this problem i create a jsbin with tabed mode and normal bod .
i have same problem with other directives of angular-ui bootstrap like modal
I know this was asked a while ago.. but for the benefit of anyone else seeing this page.
When an angular binding (such as ng-model) is retrieving a value it will travel up the scope hierarchy until it finds it.. however when setting a value it wont travel up the hierarchy. This is because it is based on how javascript prototype inheritance works.
If you follow this logic then if you bound to a property of an object the binding would then need to travel up the hierarchy to fetch that object and then set a value on it.. therefore as per the updated jsbin note that on the parent controller i am initialising an object on the scope. $scope.colors = {}; and then binding to properties on that object.
<input colorpicker="rgba" type="text" ng-model="colors.back1Color" />
<input colorpicker="rgba" type="text" ng-model="colors.backColor" />
As a rule, Miško Hevery said if your ng-model doesn't have a dot '.' you are probably doing it wrong.
Drammys answer may also work (because he is essentially binding to the 'vm' object, but this is a different style for controllers, along with 'Controller As' syntax and is optional)
I got it working by defining the controller as vm and populating the vm object in the controller...
<body ng-controller="mainCtrl as vm">Normal
<input colorpicker="rgba" type="text" ng-model="vm.back1Color" /><hr/>
<tabset><tab heading="In Tab">
<input colorpicker="rgba" type="text" ng-model="vm.backColor" />
</tab></tabset>
var app = angular.module('app',['colorpicker.module','ui.bootstrap']);
app.controller('mainCtrl',function($scope){
var vm = this;
vm.backColor = '';
vm.back1Color = '';
$scope.change = function(){
alert(vm.backColor);
};
$scope.change1 = function(){
alert(vm.back1Color);
};
});
Personally I prefer to define all the controller properties I wish to expose to the view on this "vm" object in the controller and then declare the controller as vm in the view and bind to the vm object's properties. It feels neater and better defined to me.
Updated the jsbin here.