I have a pretty typical form with some inputs and a submit button, however when I try to use jQuery's find() method, I get some annyingly inconsistent results. The are as follows:
$("#frmContact").find(":submit") -> undefined is not a function
$("#frmContact").find(".btn") -> works
$("#frmContact").find(".btn.secondary") -> undefined is not a function
$("#frmContact").find("input[type=submit]") -> works
$("#frmContact input:submit") -> undefined is not a function
$("input[type=submit]", "#frmContact") -> undefined is not a function
$("form").find("input") -> works
$("form").find("input[type=submit]") -> undefined is not a function
What's going on here and how do I fix this?
I'm using jQuery 1.11 after upgrading from 1.9 hoping that it will fix the issue. There's also Angular on the page and I'm calling this code from the console after everything is loaded.
My form, just in case you need it is as follows [EDIT] updated to show actual HTML output with Angular classes and directives:
<form ng-submit="saveContact($event, '/applicants/update_contact?id=1593')" class="ng-pristine ng-valid" _lpchecked="1" id="frmContact">
<h4 class="section-header">Applicant Contact Information</h4>
<field id="email" type="text" model="applicant.email" label="Email address" class="ng-isolate-scope">
<div ng-class="['field', isRequired()]" class="field"> <!-- Text/File/Password Field -->
<label ng-bind="label" class="ng-binding">Email address</label>
<input type="text" ng-model="model" class="ng-pristine ng-valid">
</div>
</field>
<div class="field">
<input type="submit" value="Save" class="btn secondary">
</div>
</form>
My JavaScript libraries are loaded in this order:
jQuery 11
jQuery UI
Angular
My app.js
Scripts are loaded at the bottom of the page.
AngularJS comes with JQLite, a lightweight smaller verison of jQuery, which is the one you are using here and that gives you unexpected results.
In order for Angular to works with the full jQuery, you need to make sure that you load jQuery before Angular. So watch your <script> tags order.
So it turns out the hand that held the knife to my throat was my own.
Earlier in the application's development it was useful to add a couple helper methods on the Object prototype by doing Object.prototype.findId = function() { ... }. Turns out this raised all sorts of hell when trying to perform the find() method in jQuery.
I fixed it by turning this:
Object.prototype.myMethod = function() { ... }
into this
var specialObject = function(object) {
return {
myMethod: function() { ... }
}
}
I didn't realize that my earlier approach was such bad practice until I read this: Extending Object.prototype JavaScript
Thank you all for your help, guys.
Related
I'm trying to create a page that requires buttons/tags similar to following image using html:
I'm not sure what these buttons are called. Ultimately I want to create them dynamically since what buttons need to be created are different from different users.
Any suggestions are greatly appreciated. Thanks.
These things are called Chips. If you are using angular, then you can look at the demo here.
You can implement such functionality using jQuery or core javascript.
You can use this jquery readymade plugin
Demo - http://xoxco.com/projects/code/tagsinput/example.html
GitHub Link : https://github.com/xoxco/jQuery-Tags-Input
A solution to this in Angularjs would be to create a controller for your form that determines whether or not the browser is allowed to display your cancel button. This can be created using the following code:
var app = angular.module('formExample', [])
app.controller('ExampleController', ['$scope', function($scope) {
$scope.canCancel = false;
$scope.updateCancelVal = function(myForm) {
$scope.canCancel = $scope.myForm.$valid;
};
}]);
And then in your html, it would look like:
<div ng-controller="ExampleController">
<form name="myFormName">
Name: <input ng-keyup="updatCancelVal(myFormName)" type="text" ng-model="user.name" /><br>
Email: <input ng-keyup="updatCancelVal(myFormName)" type="email" ng-model="user.email" /><br>
<button ng-show="canCancel" href="myCancelLink.html"> Cancel </button>
</form>
</div>
Ultimately, this makes it so that the Cancel button is only shown when canCancel is true. And on each key input in each of the separate inputs, this value is updated until the form is valid. If you need more aid in implementing this, lmk and more detail will be added!
I used to use Jquery extensively. Now that I stumbled upon Angularjs, I am trying understand how it works and I have been really excited about the AutoMagic way it works. For example, am able to do the below process of hiding and showing few blocks just by using ng-click, ng-hide & ng-show.
<form id="signup-form" ng-submit="processForm()" ng-hide="showConfirm" >
<input type="text" name="user" ng-model="name">
<button type="submit" id="submit" ng-click="showConfirm = ! showConfirm">Submit</button>
</form>
<div class="col-md-12 confirmation" ng-show="showConfirm">
<h2 >Thanks alot for your feedback.</h1>
</div>
But, I am still wondering how can I do the same from code, say from a controller. In Jquery one way to do would be like:
$( "#submit" ).click(function() {
$(".confirmation").show();
$("#signup-form").hide();
});
And maybe if I want to validate the form I can use .preventDefault(); in Jquery and do something. How does all this work in AngularJs?
Just change the model value in your controller: showConfirm = !showConfirm;
This will update your view automatically using the ng-hide and ng-show directives you already have in place.
Better yet, call a scoped function like:
$scope.toggleConfirm = function() { showConfirm = !showConfirm; }
...and call that in your view using ng-click="toggleConfirm()" to keep your code DRY.
Since Angular-UI-Mask is acting oddly, I'm using jquery-inputmask to some of my inputs, but when an input is dynamically inserted ny Angular it gets no mask:
<li ng-repeat="item in items">
<input type="text" name="birth_date" class="span2 format_date" ng-model="birth_date" placeholder="Data de Nascimento" required />
</li>
This is the related script
<script type="text/javascript">
jQuery(document).ready(function(){
$(".format_date").inputmask("99/99/9999");
});
</script>
Is there anything I can do to force it to set the mask to new inputs?
jQuery plugins like jQuery.inputMask work by (as your code shows) attaching behaviour to DOM elements when the document is 'ready'. This will run once, and never again, so for dynamically-added content this approach doesn't work.
Instead, you need something that will run whenever the corresponding DOM is changed. So whenever an 'item' in your 'items' list is added, the element is added and the corresponding jQuery function is run against that element. You need to use AngularJS for this and you could write your own directive, but thankfully, someone has already written the code for you: the jQuery Passthrough plugin as part of Angular UI's UI.Utils.
Here is a working Plunkr.
You need to include the script at the top, like so (I downloaded it from GitHub):
<script src="ui-utils.jq.js"></script>
Load the module into AngularJS, for example:
var app = angular.module('myApp', ['ui.jq']);
And then use the directive in your HTML markup:
<input type="text" ui-jq="inputmask" ui-options="'99/99/9999', { 'placeholder': 'dd/mm/yyyy' }" />
In AngularJS, any inline javascript code that included in HTML templates doesn't work.
For Example:
main.html file:
<div ng-include="'/templates/script.html'"></div>
And script.html file:
<script type="text/javascript">
alert('yes');
</script>
When I open main page, I expect an alert message that say 'yes' but nothing happens. I think some security restrictions in the AngularJS is preventing inline scripts, but I couldn't find any workaround about that.
Note: I don't use jQuery or any other framework, only AngularJS 1.2.7.
jQlite does not support script tags. jQuery does, so the recommendation is to include jQuery if you need this functionality.
From Angular's Igor Minar in this discussion:
we looked into supporting script tags in jqlite, but what needs to be
done to get a cross-browser support involves a lot of black magic. For
this reason we decided that for now we are just going to recommend
that users use jquery along with angular in this particular case. It
doesn't make sense for us to rewrite one third of jquery to get this
working in jqlite.
Here's the related github issue jqLite should create elements in same way as jQuery where Igor sums up, before closing the issue, with this:
This is too much craziness for jqlite, so we are not going to do it.
Instead we are going to document that if you want have script elements
in ng:include or ng:view templates, you should use jquery.
demo plunker with jquery
Angular uses the $sanitize on ng-include directives which strips out scripts. A better approach for templates is to create a controller for that template.
It is better to use an individual controller for templates.
In template.html
<form role="form" ng-controller="LoginController">
<input type="text" placeholder="Email" ng-model="email">
<input type="password" placeholder="Password" ng-model="password">
<button class="btn btn-success" ng-click="login()">Sign in</button>
</form>
In the LoginController you can use whatever code you want
angular.module('myApp.controllers', []).
controller('LoginController', [function() {
alert('controller initialized');
}])
The event triggered when ng-include adds content is $includeContentLoaded. Your scripts should be included in this event:
For example (Plucker Demo):
function SettingsController($scope, $window) {
$scope.template={};
$scope.template.url = "demo.html";
$scope.$on('$includeContentLoaded', function(event){
$window.alert('content load');
});
}
Additionally you can set an init function using the onload attribute:
html
<div ng-include="template.url" onload="alertMe()" > </div>
</div>
Controller
$scope.alertMe=function(){
$window.alert('sending alert on load');
}
Include jQuery and change order of the angular.js and jquery.js. jQuery must be first, otherwise it does not work
It is my first time using knockoutjs so just trying to get my head around it.
I am trying to map some json to some html inputs with the knockoutjs mapping plugin.
I have the following json which I am receiving ok.
{"firstname":"it","lastname":"worked"}
I am mapping it with the code below:
var myProgram{
viewModel : {},
$.post(myServer, {}, function(data) {
viewModel = ko.mapping.fromJS(data);
});
}
And then trying to bind it...
<input type="text" data-bind="value: firstname" id="text-firstname" placeholder="Text input" value="" data-mini="true" required />
However it doesn't work, and I'm not really sure where to look next to debug it. Is anybody able to help?
fixed with:
ko.applyBindings(viewModel);
Which is missing from the mappings getting started docs.