I have applied ng-model and ng-change directives on input type text, that shows color in hexa that can be changed from color panel as shown.
<input type="text" ng-model="colors.primary_color"
ng-change="colorChanged()" class="input-control"
placeholder="Primary Color"
color-picker
color-picker-model="primaryColorModel"
color-picker-position="{{colorPickerPosition}}">
<button class="btn-sidebar">
<svg width="20px" height="21px">
<path ng-style="{fill: primaryColorModel}" d="M10.000,3.429 C5.865,3.429 2.500,6.793 2.500,10.928 C2.500,15.063 5.865,18.427 10.000,18.427 C10.000,14.550 10.000,7.089 10.000,3.429 M10.000,0.929 C15.523,0.929 20.000,5.406 20.000,10.928 C20.000,16.450 15.523,20.927 10.000,20.927 C4.477,20.927 -0.000,16.450 -0.000,10.928 C-0.000,5.406 4.477,0.929 10.000,0.929 L10.000,0.929 Z"
/>
</svg>
</button>
Now when I open color panel and change colors, new hexa code shows up in input type text, but colorChanged function doesn't trigger. It only triggers when I click on text box and write some thing.
I want it to be triggerd when I remove any character or value is changed from color panel.
I have tried with $watch like so
$scope.colors = {
primary_color: "#008fff",
secondary_color:"#008fff",
text_color: "#008fff"
}
$scope.$watch('colors', function (nval, oval) {
console.log(nval);
});
$scope.colorChanged = function() {
$rootScope.$broadcast('color-change', {colors: $scope.colors});
}
But it doesn't trigger either.
If I use $apply, it says you are already in digestive cycle.
If you place the relevant markup inside a <form> element and give the <input> a name :
<form name="form">
<input name="primary_color" type="text" ng-model="colors.primary_color"
ng-change="colorChanged()" class="input-control"
placeholder="Primary Color"
color-picker color-picker-model="primaryColorModel"
color-picker-position="{{colorPickerPosition}}">
...
</form>
Then you can programmatically trigger the ng-change directive by using $setViewValue() with no params :
$scope.form.primary_color.$setViewValue()
Will trigger ng-change as the ng-model was changed without actually changing it.
demo -> http://plnkr.co/edit/PmthIfblkPkbKgRInLBc?p=preview
If you are using this plugin, then the variable you specify in color-picker-model attribute is treated as the binding variable for the color picker. So to detect changes to the color picked, you can watch that variable. In your case:
$scope.$watch('primaryColorModel', function(nval, oval) {
//your code here
});
I can't tell which plugin you used for, but regardless unless it was built with angular you'll likely have to wire up a callback that runs a $rootScope.$apply(). The reason being is that the piece of code is happening outside angulars eco-system and it needs to be notified to re-run. See my similar answer here: AngularJS: ng-repeat list is not updated when a model element is spliced from the model array
In this AngularJS controller for a pre-filled form, fetching the data is triggered by an event using $broadcast and $on. However, when the data updates, only some of the corresponding fields get updated in the view.
$scope.currentHouse = {};
$scope.$on('houseInfoLoad', function(event, data) {
$scope.currentHouse = data.houseDetail; //does not refresh the view
console.log($scope.currentHouse); //output is correct
//the next three calls refresh the corresponding fields in the view
$scope.changeGarageRadioValue($scope.currentHouse.hasGarage);
utils.setSelection($scope.houseKeywords, $scope.currentHouse.keyword.id);
utils.setSelection($scope.houseTypes, $scope.currentHouse.type.id);
});
changeGarageRadioValue() essentially does what it says, and utils.setSelection(list, id) adds a selected = true property to the element of the list that has the id. This has the effect of setting the value of a select field (using isteven's multi-select plugin).
The view has a few text fields bound to properties of $scope.currentHouse, as well as these radio buttons and select fields.
The result is that the text fields sometimes do not get updated, however the select and radio buttons do.
Here's what I tried unsuccessfully:
Wrapping everything in a $timeout();
Calling $scope.$apply() after setting $scope.currentHouse (throws an error saying that we are already inside an $apply())
Changing the initial definition of $scope.currentHouse from {} to an object with each of the fields set to null.
Can anyone see what I am missing, or how to force trigger the refresh?
EDIT : with extracts from the view :
A text field:
<label>ADDITIONAL DESCRIPTION</label>
<div>
<input type="text" ng-model="currentHouse.additionalDescription" class="input-mandatory" value=""/>
</div>
A multi-select:
<label>TYPE</label>
<div>
<div directive-id="houseType" multi-select input-model="houseTypes" output-model="currentHouse.type" button-label="text" item-label="text" selection-mode="single" default-label="Select" tick-property="selected" ></div>
</div>
The radio buttons :
<div><label>HAS GARAGE</label></div>
<div>
<div id="radiobuttonNo" ng-click="changeGarageRadioValue(false);">
NO
</div>
<div id="radiobuttonYes" ng-click="changeGarageRadioValue(true);" class="active">
YES
</div>
</div>
EDIT #2 as per Alok Singh's suggestion:
I tried putting data.houseDetail into $scope.currentHouse.house instead of $scope.currentHouse directly, and changing the view accordingly. Still no results.
$scope.currentHouse = data.houseDetail
You cannot get the updated value of currentHouse because its a model.
So change the above code i.e
$scope.currentHouse.house = data.houseDetail
In Backbone is there a bind a model attribute to an input field so that when the input value changes the model attribute will be automatically set to the current value?
At the moment I have the following in my view
<input type="text" name="firstname" class="form-input" value="<%- model.firstname %>" />
Then in the view I listen to the following event and set the model attribute accordingly
events: {
"keydown .form-input": "setAttribute"
},
setAttribute: function() {
//Use model.set on the attribute that was changed
}
To me this seems like a bad way of doing it. Am I missing an easier way of doing it?
That's the right way to do it with vanilla Backbone. If you would like to set up automated data binding you'll need a plugin like Epoxy.
Using Epoxy, your example would look something like:
var BindingView = Backbone.Epoxy.View.extend({
bindings: {
"[name=firstname]": "value:firstName",
}
});
This binds the model's firstName attribute to the input with name="firstname".
I'm brand new to javascript and knockout. I'm working on client side validation using knockout-validation and am having some trouble. I want textboxes that require some user input to show their error messages on blur (even if the user didn't enter anything). A problem I ran into is that I don't want the error messages to show up right away. I was able to get this working but was wondering if someone had a more elegant way to do this. The pseudo code for what I do is set a textbox's value as an observable and then subscribe that to hasfocus of the textbox. Here is the sample code of the view model and the fiddle to go with it:
self.firstName = ko.observable().extend({
required: true,
notify: 'always'
});
self.firstName.focused = ko.observable();
self.firstName.focused.subscribe(function(newVal) {
if(not the first time in the function and the value hasn't changed)
{
update the value to itself;
//if this is empty then it will trigger the "required" error message
}
});
http://jsfiddle.net/sderico/qAnxw/
I want to know if there's a nicer way to implement this functionality (or any other ways that aren't too convoluted). Thanks in advance!
You just need to specify the valueUpdate option to 'blur' on in your value binding. Then knockout will also update the value of firstName on the blur event which triggers the validation:
<input type="text" runat="server" ID="FirstName"
data-bind="value: firstName, valueUpdate: 'blur'"/>
Demo JSFiddle.
In my view model I update an observable's property. The property is bind to an input element.
After I change the value (from JS), the view updates.
The thing is I have other elements on the page that subscribes the the input's change event, which doesn't publish when the value is updated.
Update (Code):
Model:
var viewModel = {
email: ko.observable()
}
Html:
<input class="form-input" data-bind="value: email" type="email" />
JS: (as a result of some click):
$('.form-input').change(function () {
// doesn't happen
});
viewModel.email('someemail#aaa.com');
Instead of using change, use the Knockout subscribe function. Observables Documentation
viewModel.email.subscribe(function(newValue) {
// Called whenever the value is updated
doSomethingWithNewValue(newValue);
});