Firefox populates a form with my username/password. This is using knockout.js to bind the input but it won't update the values on this kind of populating. Am I missing something say on a page load? When it populates and the user hits submits, the values are blank.
(function (app, $, undefined) {
app.viewModel = app.viewModel || {};
app.login = {};
app.viewModel.login = {
userName: ko.observable(''),
password: ko.observable(''),
returnUrl: ''
};
app.viewModel.login.submit = function () {
sso.login(app.viewModel.login.userName(), app.viewModel.login.password(), app.viewModel.login.returnUrl);
};
app.login.init = function (returnUrl) {
app.viewModel.login.returnUrl = returnUrl;
ko.applyBindings(app.viewModel);
};
})(window.app = window.app || {}, jQuery);
The way that I have dealt with this in the past is to use a wrapper to the value binding that initializes the value from the element's current value.
It would look like (this one is simplified to only work with observables):
ko.bindingHandlers.valueWithInit = {
init: function(element, valueAccessor, allBindingsAccessor, context) {
var observable = valueAccessor();
var value = element.value;
observable(value);
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, context);
},
update: ko.bindingHandlers.value.update
};
So, you would use valueWithInit instead of value. You just need to make sure that ko.applyBindings is not called before the autocomplete has been able to do its job.
http://jsfiddle.net/rniemeyer/TeFAX/
I found the solution here not really satisfying. Although the approach is rather interesting, it fails when the user is choosing the account later and the browser does allow to use the stored credentials (e.g. if there are more than one credentials stored). It failed as well when you started typing in the password and deleted to get back to the original password (in Firefox at least).
Additionally, I did not really like the timeout to give the browser time - just not that nice.
My solution:
which isn't really one, but I thought I share nonetheless
Simple update our model manually before doing the login in the submit callback.
Using jQuery, something like self.password($("#password").val()) should do it.
Alternatively, using the existing bindings, triggering a change event seems to work as well - e.g. $("#password").change().
The Pros:
is only for credential fields, so probably a one time thing for your site
is simple and clean - one or two lines at the proper place
seems to always work reliably, no matter what browser, credential setup or usage pattern
The Cons:
breaks again the nice separation Knockout.js provides
is not a solution but rather a workaround
I will stick with that for now because I found it just reliable working. It would be nice to tell Knockout to reevaluate the bindings directly rather than storing the value back manually or triggering it via the change event. But I haven't found anything so far.
Just thinking a bit ahead - the same problem should arise when the browser auto-completes any form (e.g. like an address) - which means means some sort of general function doing the above would be nice (probably calling the change trigger on each input field of the form)
Edit:
Some quick code demonstrating the idea
The HTML:
<form id="myForm" data-bind="submit: login">
Email: <input type="text" data-bind="value: email" /><br/>
Password: <input type="password" data-bind="value: password" /><br/>
<button type="submit">Login</button>
</form>
And the Javascript:
function ViewModel() {
var self = this;
self.email = ko.observable("");
self.password = ko.observable("");
self.login = function() {
$("#myForm").find("input").change();
//Now the observables contain the recent data
alert(ko.mapping.toJSON(self));
};
}
Related
I'm attempting to implement form validation on a new Contact in my app using the ember-validations library. I'm currently using Ember Data with fixtures, and I've opted to place the validations in the model like the example in this video. I've been grappling with this for days now, and still can't seem to figure out why the validations aren't working. I'm not getting any indication that errors are even firing.
//app/models/contact.js
import DS from "ember-data";
import EmberValidations from 'ember-validations';
//define the Contact model
var Contact = DS.Model.extend(EmberValidations, {
firstName: DS.attr('string'),
lastName: DS.attr('string'),
});
//Create Contact fixtures
Contact.reopenClass({
FIXTURES: [...]
});
Contact.reopen({
validations: {
firstName: {
presence: true,
length: { minimum: 2 }
},
lastName: {
presence: true
}
}
});
export default Contact;
I'm new to Ember, and have been advised to put the following logic in routes instead of the controller. I haven't seen any examples of this being done with ember-validations, so I'm unsure if that's my issue regarding validations.
app/routes/contacts/new.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.createRecord('contact');
},
actions: {
createContact: function() {
var contact = this.get('currentModel');
this.transitionTo('contacts');
contact.save();
alert(contact.errors);
},
cancelContact: function() {
var contact = this.get('currentModel');
contact.destroyRecord();
this.transitionTo('contacts');
}
}
});
My other suspicion is that I may not be handling the errors in html correctly?
//app/templates/contacts/new.hbs
{{#link-to 'contacts' class="btn btn-primary"}}Contacts{{/link-to}}
<form>
<label>First Name:</label>
{{input type="text" value=model.firstName}}<br>
<span class="error"></span>
<label>Last Name:</label>
{{input type="text" value=model.lastName}}<br>
<span class="error"></span>
</form>
<button {{action "createContact"}} class="btn btn-primary">Submit</button>
<button {{action "cancelContact"}} class="btn btn-warning">Cancel</button>
<br>
Here is my controller
//app/controllers/contacts.js
import Ember from "ember";
export default Ember.Controller.extend({
});
I'm enjoying Ember, but this issue is stonewalling me greatly. Any help would be much appreciated.
I'm going through this exact thing and have some advice. First I would say validate where you need to ask something if it is valid. You might need to do this on the component if it's a form, you might need to do this on a model if you want to ensure it's valid before saving, or maybe on a route if there are properties there that you're wanting to check.
In any case whatever method you pick, I would highly recommend using the ember-cp-validations addon. For what it's worth, Stephen Penner (ember.js core team) has contributed to the addon, too. It's all ready for Ember CLI as well.
The setup is actually very similar to what you're doing, but instead of reopening the class, you would define with it a mixin (example from their docs). To create the mixin that's used they have a factory called buildValidations. The nice thing is that you can use this on any Ember object.
Once you've defined your validation and mixed it into the create of your object, ie: Ember.Object.create(Validations, {}); where Validations is the mixin you've created just above (like in the docs). You are all set.
Within scope of that object you now have a validations property on the object, so something like:
var Validations = buildValidations({
greeting: validator('presence', true)
});
export default Ember.Object.create(Validations, {
greeting: 'Hello World',
actions: {
announce: function() {
alert('The current validation is: ' + this.get('validations.isValid'));
// per property validation is at:
alert('The individual validation is: ' + this.get('validations.attrs.greeting.isValid'));
}
}
})
Handlebars:
Looks like the form is {{ validations.isValid }}.
You can also <a {{action announce}}>announce the validation</a>.
Also, take a look at all the docs, there are is even more properties and use cases that this addon takes care of, including handlebars helpers, ajax/async resolution of validation, and some validators to use. If you don't find the one you're after make a function validator. Using the function validator all over, easy, make it re-usable with ember generate validator unique-username.
Hope this gets you off in the right start. This is a relatively new project but has decent support and responses on the issues has been quick.
Should also mention that because these validations are based on computed properties they work in an "Ember way" that should work great, including your models.
I have a view with 2 select boxes which are "cascading". A user selects a value from the first box and the second is populated based on the new value. This is done with Select2's query option, and works fine on the first load of the page. However, when I post the page and then render it, both select boxes already have values (say A and 1), but the dependent checkbox is not initialized. I have done a few things with initSelection and it didn't help much, sometimes just getting me into an loop.
What I am trying to do is this:
Link the two boxes
When the first box changes, reset the data in the second box and clear the value
When the page is re-drawn, and a value has already been selected (e.g. response to POST)
Go to server and get the data
Show the correct value for the existing <input type='hidden' value='xxx'>
if that value exists in the list, of course
if not, set value to blank (optionally fire jquery validation
Searching/constant querying is not needed. Just load once on change
I am thinking about changing this entire, so if this is really the wrong way to go about this, I'd be happy to know.
// caches ajax result based on `data`
// if data has been requested before, retrieves from the cache (nothing special)
// based on other code that did it all inside the `query` function directly
var locationsCache = new AjaxCacheClassThing( {
url: '...',
data: function() { return { masterId: $('#ParentBox').val(); } }
});
$(function() {
$('#ParentBox').change(function () {
$('#ChildBox').select2('data', null);
});
$('#ChildBox').select2({
query: locationsCache.queryCallbackHandler,
selectOnBlur: true,
});
});
The HTML uses the standard MVC helpers, and the HTML is rendered just fine.
#Html.DropDownListFor(m => m.ParentBox, SelectListOfStuff) // standard <select>
#Html.HiddenFor(m => m.ChildBox)
Here is how this scenario goes:
ParentBox is required (no empty option)
First Load: there is no value selected
Open the DependentBox
Ajax query issues correctly
Dropdown populates as expected
Second Load
Master box selects value just fine
ChildBox hidden input has value="xx" just fine
It does not show a selected item
Clicking dropdown populates the box as expected (from cache)
After some time spent, and lots of time on here and other places, I figured out how this all works (at least some parts of it!). Way simpler than I thought it was, but still surprised this isn't supported out of the box in some way. Seems like a really common request.
query and ajax and initselection aren't that useful in this scenario
They query each time a the search box changes (not desired)
They complicate everything
You need to init the select2 manually
If you use { data: ... } then you don't need query or ajax
Set the "value" on your hidden input if you have one, so the item gets selected
You have to recreate the box when you get new data
It is really simple. This is the simplest case, using no extra features or attributes
Javascript:
$(function() {
$('#ParentBox').change(createChildSelect2);
createChildSelect2();
});
function createChildSelect2() {
makeAjaxRequest( function( newData ) {
$('#ChildBox').select2( { data: newData } );
});
}
function makeAjaxRequest(callback) {
// calls a.jsp?parentId={?} and then the callback when done.
jQuery.ajax({
url: 'a.jsp', dataType: 'json',
data: function() {
return { parentId: $("#parentBox").val() };
}
})
.done(function (data) {
callback(data);
});
}
The HTML is all the same. A type=text and type=hidden both work:
<select id="ParentBox">
<option ... >
<option ... >
<select>
<input id="ChildBox" type="hidden" class="input-medium" value="1"/>
Or using Razor:
#Html.DropDownListFor(m => m.MasterBox, SelectListOfStuff) // standard <select>
#Html.HiddenFor(m => m.DependentBox)
I'm trying using Backbone.Marionette to build an application. The application gets its data through REST calls.
In this application I created a model which contains the following fields:
id
name
language
type
I also created an ItemView that contains a complete form for the model. The template I'm using is this:
<form>
<input id="model-id" class="uneditable-input" name="id" type="text" value="{{id}}"/>
<input id="model-name" class="uneditable-input" name="name" type="text" value="{{name}}" />
<select id="model-language" name="language"></select>
<select id="model-type" name="type"></select>
<button class="btn btn-submit">Save</button>
</form>
(I'm using Twig.js for rendering the templates)
I am able to succesfully fetch a model's data and display the view.
What I want to do now is populate the select boxes for model-language and model-type with options. Language and type fields are to be restricted to values as a result from REST calls as well, i.e. I have a list of languages and a list of types provided to me through REST.
I'm contemplating on having two collections, one for language and one for type, create a view for each (i.e. viewLanguageSelectOptions and viewTypeSelectOptions), which renders the options in the form of the template I specified above. What I am not sure of is if this is possible, or where to do the populating of options and how to set the selected option based on data from the model. It's not clear to me, even by looking at examples and docs available, which Marionette view type this may best be realized with. Maybe I'm looking in the wrong direction.
In other words, I'm stuck right now and I'm wondering of any of you fellow Backbone Marionette users have suggestions or solutions. Hope you can help!
Create a view for a Select in my opinion is not needed in the scenario that you are describing, as Im assuming that your languages list will not be changing often, and the only porpouse is to provide a list from where to pick a value so you can populate your selects in the onRender or initializace function of your view using jquery.
you can make the calls to your REST service and get the lists before rendering your view and pass this list to the view as options and populate your selects on the onRender function
var MyItemView = Backbone.Marionette.ItemView.extend({
initialize : function (options) {
this.languages = options.languages;
this.typeList = options.typeList;
},
template : "#atemplate",
onRender : function () {
this.renderSelect(this.languages, "#languagesSelect", "valueofThelist");
this.renderSelect(this.typeList, "#typesSelect", "valueofThelist")
},
renderSelect :function (list, element, value) {
$.each(list, function(){
_this.$el.find(element).append("<option value='"+this[value]+"'>"+this[value]+"</option>");
});
}
})
var languagesList = getLanguages();
var typeList = getTypesList();
var myItemView = new MyItemView({languages:languagesList,typeList :typeList });
Hope this helps.
I am learning ASP.NET MVC. I have to submit a to controller side after validation in client-side(in jquery). How this can be done? Should i use <form action="#" method="post"> instead of <form action="Controller/Method" method="post"> and add an event handler in click event of submit button of , to send via ajax etc? What should i do? pls help
You are on the right track, and what you suggested will work.
A better method would be to leave the original action intact, providing backwards compatibility to older browsers. You would then create the event handler as normal, and include code to prevent the default submit behavior, and use ajax instead.
$('#submitbutton').live('click', function(e){ e.preventDefault(); });
The easiest way to do this is to use the jQuery forms plugin.
This is my go-to plugin for this type of thing. Basically it will take your existing form, action url etc and convert the submission to an ajax call automatically. From the website:
The jQuery Form Plugin allows you to easily and unobtrusively upgrade
HTML forms to use AJAX. The main methods, ajaxForm and ajaxSubmit,
gather information from the form element to determine how to manage
the submit process. Both of these methods support numerous options
which allows you to have full control over how the data is submitted.
It is extremely useful for sites hosted in low cost web hosting
providers with limited features and functionality. Submitting a form
with AJAX doesn't get any easier than this!
It will also degrade gracefully if, for some reason, javascript is disabled. Take a look at the website, there are a bunch of clear examples and demos.
This is how I do:
In jQuery:
$('document').ready(function() {
$('input[name=submit]').click(function(e) {
url = 'the link';
var dataToBeSent = $("form#myForm").serialize();
$.ajax({
url : url,
data : dataToBeSent,
success : function(response) {
alert('Success');
},
error : function(request, textStatus, errorThrown) {
alert('Something bad happened');
}
});
e.preventDefault();
});
In the other page I get the variables and process them. My form is
<form name = "myForm" method = "post">//AJAX does the calling part so action is not needed.
<input type = "text" name = "fname"/>
<input type= "submit" name = "submit"/>
<FORM>
In the action page have something like this
name = Request.QueryString("fname")
UPDATE: As one of your comment in David's post, you are not sure how to send values of the form. Try the below function you will get a clear idea how this code works. serialize() method does the trick.
$('input[name=submit]').click(function(e){
var dataToBeSent = $("form#myForm").serialize();
alert(dataToBeSent);
e.preventDefault();
})
I am currently trying to build a little widget that will retrieve a list of artists based on a username.
The Ruby method requires a username parameter after which an API call is made that retrieves the actual array of strings.
The web page has an input field where the user can fill out his/her username. My goal is to immediately call the ruby method and display the list of artists. My problem is being able to use the actual form input as the parameter. I figured this would be relatively easy with params[:user], in the same way it's done in a Sinatra post method. Alas, turns out it isn't.
I tried both a JS approach and directly calling the method after :onkeyup.
Javascript:
userChanged = function() {
var user = document.getElementById("username");
if (user.value.length != 0){
artists = #{RFCore::get_artists(:name => params[:user]).to_json};
art_list.innerHTML = artists
};
};
:onkeyup
:onkeyup => "art_list.innerHTML = #{RFCore::get_artists(:name => params[:user])[0]}"
I have substituted params[:user] with all variations I could think of such as "#{user}" and user.
The errors returned are undefined method []' for params[:user] and undefined local variable or methoduser' for "#{user}" and user.
Perhaps there is an easy solution to this; but the feeling is starting to creep up on me my approach is wrong to begin with. I am open to any other way of achieving this.
As far as I understood, you are generating that JavaScript dynamically. So when your Ruby code produces it, it evaluates that RFCore::get_artists expression when you are generating the JavaScript code, not when the user interacts with the web page.
If that's the case, I recommend:
Use jQuery. It makes your life much easier.
When there's some user interaction (e.g., a key press), use Ajax to communicate with your server to get back a list of artists.
Here is a small Sinatra application that demonstrates this approach:
require 'sinatra'
get '/' do
<<html
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function userChanged()
{
$.get('/get-artists',
{username: $('#username').val()},
function(data){
$('#artists').html(data);
});
}
</script>
User: <input id="username" type="text">
<button onclick="userChanged();">Look up</button>
<div id="artists"/>
html
end
get '/get-artists' do
"Generate here list for user #{params[:username]}"
end
Please notice that the above code is just an example. The HTML generated is all wrong, no template language is being used, etc.