How to properly use KnockoutJS visible bindings? - javascript

I have a quick (hopefully simple) problem with KnockoutJS and the visible binding. I just can't seem to get it working for the code below. All it is supposed to do is display a form while "signedIn" is false and once the form is submitted the form should disappear and it should display "You are signed in as (username)".
<form class="pad-bottom" data-bind="visible: !signedIn, submit: signIn" onsubmit="signIn()">
<div class="form-group">
<label for="username">Sign In</label>
<input class="form-control" type="text" name="username" id="username" placeholder="Enter your userame" />
</div>
<button type="submit" class="btn btn-primary">Sign In</button>
<br />
</form>
<div data-bind="visible: signedIn">
<p>You are signed in as <strong data-bind="text: username"></strong></p>
var vm = {
username: ko.observable(),
signedIn: ko.observable(false),
signIn: function () {
vm.username($('#username').val());
vm.signedIn(true);
}
}
Currently none of my visible bindings seem to be working as it always shows the form and always shows the "You are signed in as" text. I feel like I'm missing something obvious but I hope a set of fresh eyes might help me find it. I'm using Visual Studio 2013 if that is of any help.

With Knockout observables you don't have to call the observable function by using () if you are binding directly to the observable such as data-bind="visible: signedIn. But as soon as you do something on the observable in the binding such as negate it or if you use an equality check then you will need to call the observable function to read the value first before negate it or comparing it.
So in your code you need to call the observable function as follows:
data-bind="visible: !signedIn()
In light of this I think it's best practice to always call the observable function to avoid mistakes such as this.
Instead of using jquery to get the value of username use Knockout value binding to do that.
Since you are using the Knockout submit binding there is no need to use onsubmit.
<form class="pad-bottom" data-bind="visible: !signedIn(), submit: signIn">
<div class="form-group">
<label for="username">Sign In</label>
<input data-bind="value: username" class="form-control" type="text" name="username" id="username" placeholder="Enter your userame" />
</div>
<button type="submit" class="btn btn-primary">Sign In</button>
<br />
</form>
var vm = {
username: ko.observable(),
signedIn: ko.observable(false),
signIn: function () {
vm.signedIn(true);
}
};
JsFiddle

Related

Prevent angular form from submitting if input is blank

I have an Angular form inside a ng2 popup:
<popup>
Sign up for our Newsletter! <form #f="ngForm" (ngSubmit)="onSubmit()" novalidate>
</button> <input type="email"/>
<button>Submit</button>
</form>
</popup>
<button class="submit" (click)="ClickButton()">Sign up for our Newsletter </button>
here is the onClick event function:
constructor(private popup:Popup) { }
testAlert() { ClickButton(){
alert("Newsletter event works"); this.popup.options = {
widthProsentage: 15,
showButtons: false,
header: "Sign up for our Newsletter!",
}
this.popup.show(this.popup.options);
}
It works fine but I am able to submit her even if the input is blank, how can I make so that it does not submit if it is clicked empty
I tried using RegEx but it did not work
Consider adding validation.
Something like this:
<div class="form-group row">
<label class="col-md-2 col-form-label"
for="userNameId">User Name</label>
<div class="col-md-8">
<input class="form-control"
id="userNameId"
type="text"
placeholder="User Name (required)"
required
(ngModel)="userName"
name="userName"
#userNameVar="ngModel"
[ngClass]="{'is-invalid': (userNameVar.touched || userNameVar.dirty) && !userNameVar.valid }" />
<span class="invalid-feedback">
<span *ngIf="userNameVar.errors?.required">
User name is required.
</span>
</span>
</div>
</div>
You can then disable the submit button if the fields are not valid:
<button class="btn btn-primary"
type="submit"
style="width:80px;margin-right:10px"
[disabled]="!loginForm.valid">
Log In
</button>
(ngSubmit) is built-in event emitter inside of Angular ngForm and is directly related to button element which is kind of a trigger for form submission.
Therefore, as lealceldeiro said, you only need onSubmit function and button intended for submission inside of your form tag.
Please provide live demo so we can see the whole file (.ts particularly).
Setting the validation properly depends on what kind of forms you're going to use (template or ReactiveForms).
See more about proper ngForm usage in official documentation.

I can't access ng-model from a controller [AngularJS]

I'm developing an e-commerce site for learnign purposes.
HTML:
<div class="container">
<form class="log-in-form" ng-controller="ControllerLogin">
<div class="form-group">
<label for="loginEmail">Email address</label>
<input type="email" class="form-control" id="loginEmail" placeholder="Email" ng-model="email">
</div>
<div class="form-group">
<label for="loginPass">Password</label>
<input type="password" class="form-control" id="loginPass" placeholder="Password" ng-model="password">
</div>
<button class="btn btn-default" ng-click="authenticate()">Login</button>
</form>
</div>
Angular javascript
app.controller('ControllerLogin', ['$scope', '$http', 'ServiceLogin', function ($scope, $http, ServiceLogin) {
$scope.authenticate = function () {
console.log($scope.email);
ServiceLogin.auth($scope.email, $scope.password)
.success(function (data) {
alert(data);
});
}
}]);
Every time I console.log the $scope.email, or password. It throws an error of undefined. I'm just starting on angular and I don't know why is not getting the models, I thinks my code is correct. Any help you can give I will be gratefull.
From Angular site:
Note that novalidate is used to disable browser's native form validation.
The value of ngModel won't be set unless it passes validation for the input field. For example: inputs of type email must have a value in the form of user#domain.
Reference: https://docs.angularjs.org/guide/forms
So the reason it may be blank is that it's not a valid email.
You can look at their demo for the email type and see it in action.
I recommend adding:
{{email}}
<br>
{{password}}
somewhere in your html within the controller's HTML scope for your own debugging.
Good luck.

angular's ng-submit() directive does not submit while pressing enter on one of text fields

I've constructed a simple form using angular.
I want that once the user enter some value and then press enter - the ng-click function (in this case updateMsg({name: name,room: room})) will be run.
However, this code does not work like that.. the function run only after pressing the button (not like I want - enter keyboard value, then enter..)
Code is below...
help please?
Thanks
<body>
<div class="Member">
<h1>Sign In</h1>
<form name="myForm" ng-submit="updateMsg({name: name,room: room})">
Please enter your details:
<br>
Name: <input name="name" ng-model="name" autocomplete="off">
<br>
Room: <input name="room" ng-model="room" autocomplete="off">
<br>
<button type="button" ng-click="updateMsg({name: name,room: room})">
Enter
</button>
</form>
</div>
</body>
You should not use ng-click and ng-submit directives together. Add type="submit" to your button like this:
<button type="submit">Enter</button>
and keep only ng-submit:
<form name="myForm" ng-submit="updateMsg({name: name,room: room})">
Please enter your details:
<br> Name:
<input name="name" ng-model="name" autocomplete="off">
<br> Room:
<input name="room" ng-model="room" autocomplete="off">
<br>
<button type="submit">Enter</button>
</form>
Also there is no point in doing ng-submit="updateMsg({name: name,room: room})" to pass your updated data like that. Since you are using ng-model you are ready to go. You can declare your scope vars initially in the controller and when the form gets submitted you can use them right away. Because of dual-binding your vars will be already updated:
angular
.module('myApp', [])
.controller('MemberController', ['$scope', function($scope) {
$scope.name = '';
$scope.room = '';
$scope.updateMsg = function() {
// use updated $scope.name in here
// use updated $scope.room too
}
}]);
A small plunker to help you some more.
I think the button should have type=submit instead.
<button type="submit">
instead of
<button type="button" ng-click="updateMsg({name: name,room: room})">Enter</button>
Are you calling a event.preventDefault() method so the form doesn't submit by default? Maybe share the code where you're creating the updateMsg({name: name,room: room}).

How to get form values in meteor?

I am getting an error Uncaught TypeError: Cannot read property 'value' of undefined however it is something to do with the way how I am calling the event.
Here is a skeleton of my code:
HTML
<template name="register">
<form>
<input type="text" name="username">
<input type="email" name="email">
<input type="password" name="password">
<button type="button" class="register">Register</button>
</form>
</template>
JavaScript
Template.register.events({
'click .register': function(e) {
e.preventDefault();
var getUser = e.target.username.value;
var getEmail = e.target.email.value;
var getPassword = e.target.password.value;
console.log("user: " + getUser);
}
)};
I feel like there is something to do with the click event button class, which is returning no values. I tried using the submit event, but I've no idea how to retrieve values.
First up, add the closing " after the button type attribute, secondly as this is a form, the type should be submit, and then in your event handler you should be listenning for the form submission. Currently these values don't exist on your target, because its just a button when you need to be listening on the form.
<template name="register">
<form class="form-register">
<input type="text" name="username">
<input type="email" name="email">
<input type="password" name="password">
<button type="submit" class="register">Register</button>
</form>
</template>
So now, we've added a class to the form, updated the button type. We'll now listen to the forms submission :
Template.register.events({
'submit .form-register': function(event, template) {
event.preventDefault();
var getUser = event.target.username.value;
var getEmail = event.target.email.value;
var getPassword = event.target.password.value;
console.log("user: " + getUser);
}
)};
While I've not tested this specifically, this will get you on the right track. Notice that I've added the template argument to the event handler, as this is the second argument. This gives you access to the template that you're working with as well, which is slightly nicer than the way you're using the event target right now. have a look at the docs for event maps which will talk about this second argument returning a template instance which has a number of useful methods such as find, findAll etc, checkout template instances here.
Ultimately my preferred method now for retrieving form values in a submission event, is to bind the form to a reactive dictionary and access them there, but its a more complex pattern that requires some scaffolding.
I would consider getting the values from the elements directly. So in the click handler function you would have:
var name = document.getElementById('idOfUsernameInputField').value;
And replicate this for all your fields.
I do like your suggestion #Shi-ii, by using JQuery. But every time when I use JQuery, sometimes my code stop running and says that JQuery is undefined. How can I fix it?
And here is a working solution for my problem. I replace name to id, so JQuery can access the values.
HTML
<template name="register">
<form>
<input type="text" id="username" />
<input type="email" id="email" />
<input type="password" id="password" />
<button type="button" class="register">Register</button>
</form>
</template>
JavaScript
Template.register.events({
'click .register': function(e) {
e.preventDefault();
var getUser = $("#username").val();
var getEmail = $("#email").val();
var getPassword = $("#password").val();
}
});
Try this way it's good way
Write this js as globally
$.fn.searlizeObject = function() {
var array = this.serializeArray() || [];
var formData = {};
array.forEach(function(formElem) {
formData[formElem.name] = formElem.value;
});
return formData;
}
Now call this
Template.register.events({
'click .register': function(e) {
var data = $("#userForm").searlizeObject();
console.log('my form data is ',data);
});
in this you have to write id in your form so we can get all data from form
in your code write this way
<template name="register">
<form id="userForm">
<input type="text" id="username" />
<input type="email" id="email" />
<input type="password" id="password" />
<button type="button" class="register">Register</button>
</form>
</template>
Bye Enjoy Coding !!!!
You're not getting the other content bound to your event. Because the button is not the submit input, it's not rolling up all the other inputs with it (as is demonstrated in Meteor documentation).
If your replace your <button type="button" class="register">Register</button> with <input type="submit" class="button register" value="Register"> you will have the desired behavior (where values are passed to the event handler); your handler will look like
Template.register.events({
'submit': function(e){... and be otherwise unchanged.

Pressing Enter doesn't work with AngularJS

I am having a problem with using 'enter button' on the keyboard with an angular js login form. I know this question is asked before but I believe that my problem is a bit different because I tried almost everything written on the stackoverflow questions.
So, I just want to be able to hit enter and submit the form with only using the enter key on keyboard.
Here is login html:
<!-- BEGIN LOGIN FORM -->
<form ng-submit="loginCtrl.login()" class="login-form">
<h3 class="form-title">Sign In</h3>
<div class="alert alert-danger display-hide">
<button class="close" data-close="alert"></button>
<span>
Enter any username and password. </span>
</div>
<div class="form-group">
<!--ie8, ie9 does not support html5 placeholder, so we just show field title for that-->
<label class="control-label visible-ie8 visible-ie9">Username</label>
<input class="form-control form-control-solid placeholder-no-fix" type="text" autocomplete="off" placeholder="Company/username"
ng-model="loginCtrl.username" name="username"/>
</div>
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">Password</label>
<input class="form-control form-control-solid placeholder-no-fix" type="password" autocomplete="off" placeholder="Password"
ng-model="loginCtrl.password" name="password"/>
</div>
<div class="form-actions">
<input type="submit" class="btn btn-success uppercase" value="Login">
</div>
</form>
<!-- END LOGIN FORM -->
and here is my login:
self.login = function() {
var result = self.username.split("/");
var account = result[0];
var userId = result[1];
UserService.login(userId, self.password,account).then(function(user) {
self.userAccount = user;
$state.go('home');
}, function(err) {
alert("Authentication failure: Please check your credentials. ")
});
I get user name as "companyName/Username" so it is like:
amazon/bigboby
I'm pretty sure your problem is caused by this <button> tag:
<button class="close" data-close="alert"></button>
The answer is found in the documentation:
You can use one of the following two ways to specify what javascript method should be called when a form is submitted:
ngSubmit directive on the form element
ngClick directive on the first button or input field of type submit (input[type=submit])
Note the comment about how it looks for an ng-click handler on the first button. When you are pressing ENTER to submit the form, Angular looks at the form and sees that button. It would execute the ng-click handler on that button (if it had one).
If you include the type attribute on the button, you can prevent that and let it find the actual submit button:
<button type="button" class="close" data-close="alert"></button>

Categories