I am working on setting up an application using an Angular, Express, Node, mySQL stack and I am having an issue binding the value of a checkbox. mySQL stores boolean values as a bit so the json response is coming back with { done: 1 }, however angular seems to only accept boolean or string values to bind to true/false.
I have the following model (I have also tried defining done as DataTypes.BOOLEAN to no avail):
var Todo = sequelize.define('todos', {
text: DataTypes.STRING,
done: DataTypes.INTEGER
})
my code is setting the values for that model to this:
{"todos":[
{"id":1,"text":"add my first todo","done":1},
{"id":2,"text":"Get the done toggle working","done":0}
]}
Lastly in my view I have this code (I am using jade):
li(ng-repeat="todo in todos")
input(type="checkbox", ng-model='todo.done')
{{todo.text}}
However the checkbox is not being checked. I have tried adding ng-true-value but since it only accept string values I can't set true to an integer.
How can I get angular to work with the bit value stored by the database?
Update: I have updated my node server to convert the value of done into a boolean which is working good. Is that the recommended solution or is there a better way to accomplish this? (this solution feels a bit hacky to me and I feel like there must be a built in way to accomplish this without rewriting the server response in node)
todos.retrieveAll(function(todos) {
if(todos) {
todos.forEach(function(todo) {
todo.done = Boolean(todo.done);
});
res.json({
todos: todos
});
} else {
res.send(401, "No todos found");
}
}, function(err) {
res.send(501, "Error retrieveing todos. Message: " + err);
console.log("Error: " + err);
});
<input type="checkbox" ng-model="mymodel.myvalue" ng-true-value="1" ng-false-value="0" value="myvalue">
The best way is to use ng-true-value and ng-false-value, I had an issue because my values were being sent as json_encoded array which meant that I had to include the quotes to make it compare correctly.
Script:
// this is the model object that is bound to by the checkbox (amongst other things)
// and in my case is "1" for true "0" for false - note this is an array as passed back from my data source so I am using [0] in the HTML ng-model - if you have a straight object then you would bind to myScopeBoundVar and it would be defines as something like {"active":1} or in my case the 1 would be a string.
myScopeBoundVar=[{"active":"1", "surname" : "Smith"}];
HTML
<input value="check" ng-model="myScopeBoundVar[0].active" ng-true-value="'1'" ng-false-value="'0'" class="ng-valid ng-dirty ng-valid-parse ng-touched">
Related
I have a model:
export default Model.extend({
title: attr('string'),
attributes: attr('jsonb')
});
Where attributes is a custom json filed stored as jsonb in Postgres.
let say:
{
"name":"Bob",
"city":""
}
So I can easily manipulate attributes using template
<form.element .. #property="attributes.city"/> or model.set('attributes.city','city name')
Problem: hasDirtyAttributes do not changing because technically we have old object. But when I try to copy object let say
JSON.parse(JSON.stringify(this.get('attributes')) hasDirtyAttributes works as expected
So how to write some Mixin for a Model or other workaround which on the change of any attribute property will mark hasDirtyAttributes as true. I will update whole object so doesn't matter which property actually was changed.
Same problem: https://discuss.emberjs.com/t/hasdirtyattributes-do-not-work-with-nested-attributes-json-api/15592
existing solution doesn't work for me at all:
ember-dirtier
ember-data-relationship-tracker
ember-data-model-fragments (a lot of changes under the hood and broke my app)
Update:
Some not perfect idea that help better describe what I'm want to achieve:
Let say we adding observer to any object fileds:
export default Model.extend({
init: function(){
this._super();
this.set('_attributes', Object.assign({}, this.get('attributes'))); //copy original
Object.keys(this.get('attributes')).forEach((item) => {
this.addObserver('attributes.'+ item, this, this.objectObserver);
});
}
...
})
And observer:
objectObserver: function(model, filed){
let privateFiled = '_' + filed;
if (model.get(privateFiled) != model.get(filed)) { //compare with last state
model.set(privateFiled, this.get(filed));
model.set('attributes', Object.assign({}, this.get('attributes')) );
}
}
It's works, but when I change one filed in object due to copying object objectObserver faired again on every filed. So in this key changing every filed in object I mark observed filed as dirty
The further ember development will reduce using of event listener and two-way binding, actually Glimmer components supports only One-way Data Flow. So to be friendly with future versions of emberusing one-way data flow is good approach in this case to. So In my case as I use ember boostrap solution looks like
<form.element #controlType="textarea" #onChange={{action 'attributeChange'}}
where attributeChange action do all works.
New Glimmer / Octane style based on modifier and looks like:
{{!-- templates/components/child.hbs --}}
<button type="button" {{on "click" (fn #onClick 'Hello, moon!')}}>
Change value
</button>
I want to do form validation with Vue 2. The problem is that I want to use information from the server. For each field I can add things like max string length, required, type, ... to the json result.
Does something like this already exists? Is there a common used format for this?
Is there a good plugin for Vue that I can use for this. I already found form validation plugins, but I don't want to bind each setting on each input manually.
I was thinking about a validation object that I could bind to a form. But maybe I'm reinventing the wheel?
This is how I usually do it:
In template, let's say you have something like this:
<form>
<input #keyup="keyUpHandler('firstName')" v-model="firstName" />
<input #keyup="keyUpHandler('lastName')" v-model="lastName" />
<input #keyup="keyUpHandler('email')" v-model="email" />
</form>
In JS:
data: {
firstName: '',
lastName: '',
email: ''
},
methods: {
keyUpHandler: _.throttle((type) => {
sendStuffToServer(this[type])
.then(response => {
// if there's an error, then show error
})
}, 2000)
}
I used lodash to do debounce, so sendStuffToServer will only execute when the user is done typing for 2 seconds. You may come across the debounce filter in Vue, but it's already removed in 2.0, so use lodash instead.
When Json object comes from Server, date is always stored as string.
We need to show that date value in Input box to allow Edit/Update of object. But
<Input type="date>
only understands date object (rightly so), henceforth, we need to convert date string to date object, after receiving json from AJAX call. There are couple of threads on SO, trying to achieve same, but I found accepted answers on those thread not working (not even plunker).
Convert AJAX date to Javascript date for use with ng-model
angularjs | date input not showing ng-model value
I don't want to let go type="date" (don't want to loose dtPicker of mobile browsers).
I don't want to write a line everywhere on controller, converting a date string value to date. Though it does work, but I will keep it as last resort.
I tried to solve my problem using directive, and created following directive.
I am trying to induce date object via ngModel.$formatters. Console.log inside jsonStrToDate prints str as empty string.
It is not working, What is wrong with my directive here?) :-
.html
<input type="date" name="dateOfReading" class="form-control" id ="dateOfReading"
ng-model="bpReport.dateOfReading"
json-string-to-date
min="1970-01-01" max="2099-12-31" required />
.js
window.angular.module('myApp.directives', [])
.directive('jsonStringToDate', function(){
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, ngModel) {
console.log('directive linking called');
function jsonStrToDate(str) {
console.log('input str value' + str + ', and typeof is ' + typeof str);
var d= new Date(str);
console.log(d);
return d;
}
ngModel.$formatters.push(jsonStrToDate);
ngModel.$parsers.push(function(value) {
console.log("value from parser method:- "+ value);
return value;
});
}
};
});
Right now I am using AngularJS 1.3.0 RC1
Version 1.2.20 also had same issue.
I have a form that have a three field group that on a click of a "Add New" buttom other three field group will be added. That part is working great.
I want to add a validation so all three fields are required in order to add a new group.
For reference here is the code working: http://jsfiddle.net/5g8Xc/
var ContactsModel = function(contacts) {
var self = this;
self.contacts = ko.observableArray(ko.utils.arrayMap(contacts, function(contact) {
return { firstName: contact.firstName, fathersLast: contact.fathersLast, country: contact.country };
}));
self.addContact = function() {
self.contacts.push({
firstName: "",
fathersLast: "",
country: ""
});
};
self.removeContact = function(contact) {
self.contacts.remove(contact);
};
};
Any clue on how to implement this validation? I was trying to use jquery validation to do that but I think that is possible with KnockoutJS.
Appreciate any advice.
As stated already, the validation plugin will be the most elegant, less re-inventive solution.
Edit: After commentary implementation utilizing validation plugin
With that aside, you have a couple options.
If you are confident the contact object will always contain only required fields, a not very robust implementation would be iterate over the properties of the contact ensuring each has some value.
A little more robust, but still lacking the elegance of the plugin, implementation would be to maintain an array of required fields and use that array for validation. You can reference my example for this setup. Essentially, each required property is mapped to observables. Changes made to the value of any observable property triggers (via a subscription) a mutation call for a dummy observable that is used in a computed. This is required since a computed can't call valueHasMutated. The mutation call triggers the computed to reevaluate, thus updating the UI.
Hi I'm kind of new to Knockoutjs, I am in the scenario where I want to post a form where I have for example an email address, there is an requirement that the email address needs to be unique.
On the server I check if the email address is unique or not and then returns an validationjson class for example
{
isEmailUnique: false,
isPasswordStrongEnough: true;
}
How can I with knockoutjs validation show these errors in a neat way?
I would use two different server side validators for this, since they affect different observables in the view model.
Originally taken from the knockout validation readme
ko.validation.rules['isEmailUnique'] = {
validator: function(val, param){
var isValid = true;
$.ajax({
async: false,
url: '/validation/isEmailUnique',
type: 'POST',
data: { value: val, param: param },
success: function(response){
isValid = response === true;
},
error: function(){
isValid = false; //however you would like to handle this
}
});
return isValid;
},
message: 'The Email is not unique'
};
Then on the server you need to create an endpoint that accepts POST requests where you perform your lookup and then return true or false depending on the result of the query.
To use the above validator
this.email = ko.observable()
.extend({
isEmailUnique: {
message: 'Something else perhaps? It will override the message in the validator'
}
});
You can use the very same thing for the password strength validation.
Using validators like this will fire validation when the observable changes, which can be a useful way to do validation.
I'm a bit late, but for my 2 cents worth, I would take a more generic approach such as returning a standard JSON serialized AjaxResult class from your server endpoints (such as /Register) with properties such as Data (an arbitrary container used for, for example, an updated model to re-bind with the mapping plugin), and a collection of validation message strings, etc. Then you could have an HTML validation summary which is bound to an ObservableArray and push / map the messages from your Ajax result into there. This is essentially what I've been doing with Knockout and it works nicely.