Cannot read property 'addEventListener' of null using Polymer iron-form example - polymer-1.0

I'm using Polymer to create a form based on the iron-form template here: https://github.com/PolymerElements/iron-form/blob/master/demo/index.html using the formGet form. My code is:
<form is="iron-form" id="formGet" method="get" action="/"
<paper-input name="name" label="* Name" required></paper-input>
<paper-input name="description" label="Description"></paper-input>
<paper-button raised onclick="submitHandler(event)">Submit</paper-button>
<paper-button raised onclick="resetHandler(event)">Reset</paper-button>
</form>
<script>
document.getElementById('formGet').addEventListener('iron-form-submit', display);
function display(event) {
var output = document.getElementById('output');
output.innerHTML = JSON.stringify(event.detail);
}
function submitHandler(event) {
Polymer.dom(event).localTarget.parentElement.submit();
}
function resetHandler(event) {
Polymer.dom(event).localTarget.parentElement.reset();
}
</script>
When I hit submit, I get the error:
Cannot read property 'addEventListener' of null

Inside your script try wrapping your code with a
HTMLImports.whenReady(function(){ ... });

Related

Angular - Cannot read property '$invalid' of undefined

I am creating a login page using angular and typescript. When the submit button is clicked, I would like the login function in the controller to fire, but if the form is invalid then it just returns.
This is my first time using typescript, so every time I try to put in the if statement to check if the form is invalid it throws the error Cannot read property '$invalid' of undefined.
Here is the html:
<form class="login-form" name="loginForm" ng-submit="vm.login()" novalidate>
<input type="email" name="email" placeholder="Email" required ng-model="vm.email" ng-class="{true: 'input-error'}[submitted && loginForm.email.$invalid]"/>
<input type="password" name="password" placeholder="Password" required ng-model="vm.password" ng-class="{true: 'input-error'}[submitted && loginForm.password.$invalid]"/>
<input type="submit" id="submit" ng-click="submitted=true"/>
</form>
And here is the compiled javascript:
var LoginModule;
(function (LoginModule) {
var LoginController = (function () {
function LoginController() {
}
LoginController.prototype.login = function () {
if(this.loginForm.$invalid) {
return;
}
console.log("Login was clicked, email is " + this.email + " and password is " + this.password);
};
return LoginController;
})();
LoginModule.LoginController = LoginController;
})(LoginModule || (LoginModule = {}));
angular.module('loginModule', []).controller('LoginController', LoginModule.LoginController);
It looks like the common issue with this was that people were not specifying the form name, but that is not the case here. Does anyone know why I could be getting this error?
You need the controller alias in the form name
<form name="vm.loginForm" ng-submit="vm.login()" novalidate>
While #charlietfl's answer is correct for the OP's question, this error can also be thrown if you've missed the ng-model property on an input control and are using the ui.bootstrap.showErrors $scope.$broadcast('show-errors-check-validity') method.
As per the documentation (my emphasis):
.. an input control that has the ngModel directive holds an instance of NgModelController. Such a control instance can be published as a property of the form instance using the name attribute on the input control. The name attribute specifies the name of the property on the form instance.

Form object undefined when using Angularjs blockUI

I'm using Angularjs, version 1.5, and i have specified a form in my html as follows:
<div class="row" ng-show="showForm">
<form class="form-horizontal" name="myForm" novalidate role="form">
</form>
</div>
In the corresponding controller i have a function that resets the form and calls pristine:
$scope.myForm.$setPristine();
Until now everything works fine.
I then try to use blockUI (https://github.com/McNull/angular-block-ui)
by changing the above div to:
<div class="row" ng-show="showForm" block-ui="myBlock">
so the only addition is: block-ui="myBlock"
however, when the controller code runs i get:
TypeError: Cannot read property '$setPristine' of undefined
When debugging i see that the form object does not exist! When removing block-ui="myBlock", everything works fine again.
Any ideas?
Thanks in advance
Try something like these:
function MyCtrl($scope, $timeout, blockUI) {
$scope.form = {};
$scope.submit = function() {
var myBlockUI = blockUI.instances.get('myForm');
$scope.form.myForm.$setPristine();
myBlockUI.start();
$timeout(function() {
// Stop the block after some async operation.
myBlockUI.stop();
}, 3000);
};
}
and view:
<form name="form.myForm" novalidate ng-submit="submit()" block-ui="myForm">
<input type="text">
<button>
Submit
</button>
</form>
I have same trouble like you with undefined form on $scope, but found these trick with using additional object form on SO. Plunk here.

Trigger Polymer function using form onsubmit?

I'm unable to get a form to trigger a Polymer function when it's being submitted:
<form onsubmit="return _submit()"> //_submit is not defined
<form onsubmit="return this._submit()"> //this._submit is not a function
<form onsubmit="_submit"> //_submit is not defined
<form onsubmit="{{_submit}}"> //no output
<form on-submit="{{_submit}}"> //no output
<form on-submit="_submit"> //no output
How do I bind to Polymer function?
Use iron-form:
<form is="iron-form" id="form" method="post" action="/form/handler">
<paper-input name="name" label="name"></paper-input>
<input name="address">
...
</form>
And then add a listener for iron-form-submit which is fired after the form is submitted:
Polymer({
listeners: {
'iron-form-submit': '_handleSubmit'
},
_handleSubmit: function(e) {
// Do something
}
})
See iron-form docs for more info.

Communication between Angular.js controllers and Polymer custom elements

I'm using Angular.js on one of my projects and I want to combine it with Polymer. I have some problems with the comunication between Angular.js controllers and the Polymer custom elements.
What is my problem...
For example I have an AuthService, an AuthController which uses the AuthService to send requests to the backend (Node.js with Express) and a simple login form like this:
<form role="form" ng-submit="login()">
<div>
<label for="usernameInput">Username: </label>
<input type="text" name="usernameInput" id="usernameInput" placeholder="Username" ng-model="usernameInput" required>
</div>
<div>
<label for="passwordInput">Password: </label>
<input type="password" name="passwordInput" id="passwordInput" placeholder="Password" ng-model="passwordInput" required>
</div>
<div>
<label for="rememberMeInput">Remember me: </label>
<input type="checkbox" name="rememberMeInput" id="rememberMeInput" ng-model="rememberMeInput">
</div>
<input type="submit" name="loginSubmit" value="Log in">
</form>
Everiting is working fine in this format but I want to move the form inside a Polymer custom element like this:
<polymer-element name="cg-login-form">
<template>
<div layout vertical>
<div class="error hidden">{{ error }}</div>
<form role="form" layout vertical center>
<div>
<paper-input type="text" floatinglabel label="Username" value="{{ inputData.username }}"></paper-input>
</div>
<div>
<paper-input type="password" floatinglabel label="Password" value="{{ inputData.password }}"></paper-input>
</div>
<div layout horizontal center>
<paper-checkbox role="checkbox" checked="{{ inputData.rememberBe }}"></paper-checkbox>
<div>Remember me</div>
</div>
<paper-button label="Log in" raisedbutton role="button" on-click="??????"></paper-button>
</form>
</div>
</template>
<script>
Polymer('cg-login-form', {
inputData: {
username: undefined,
password: undefined,
rememberMe: false
}
});
</script>
</polymer-element>
My problem is: How to call the login method of the AuthController on form submit and I want the Polymer element to stay Angular.js independent.
I was thinking to fire a login event with the input data and to listen for this event inside the AuthController. Then the login event handler can call the AuthContoller's login method, but I can't get the sent data with the event.
This is how I'm firing the event inside the:
<paper-button label="Log in" raisedbutton role="button" on-click="{{ login }}"></paper-button>
Polymer('cg-login-form', {
inputData: {...},
login: function() {
this.fire('login', { loginData: this.inputData });
}
});
And this is how I'm listening for the login event inside the AuthController:
// In this way the detail and the data properties of the event object are undefined
angular.element("#loginForm").on('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
// In this way the detail and the data properties of the event object are undefined
$('#loginForm').on('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
// In this way the detail property of the event object is set with the sent data
document.getElementById('loginForm').addEventListener('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
// In this way the detail property of the event object is set with the sent data
document.querySelector('#loginForm').addEventListener('login', function(event) {
console.log(event.detail);
console.log(event.data);
});
Why document.getElementById('loginForm').addEventListener() and document.querySelector('#loginForm').addEventListener() works and the other two ways doesn't work?
How can I get the sent data using jQuery or jqLite? I prefer to use them instead of using the html approach.
I will be glad if you tell me a better way for communication between Angular.js controllers and Polymer custom elements instead of events triggering.
Thank you very much and have a nice day
EDIT:
Also I can get the ng-login-form element from the DOM inside the AuthController and pass the AuthController's login method like a callback to some ng-long-form method. Then on form submit the ng-login-form can call the callback with the input data.
This will work too but I don't think that this is a good approach.
I solved it this way
In the paper-input add -- inputValue="{{ valData }}" --
for example
<paper-input label="name" id="name" class="label-input-full" inputValue="{{ valData }}">
</paper-input>
Add in button submit onclick event
for example
<paper-button class="btn-check" type="submit" icon="check" core-overlay-toggle on-click="{{fetchDataFromForm}}" >
</paper-button>
Finally in the scripts, add the function for send data to angular
For example
Polymer('name-element', {
fetchDataFromForm: function() {
USER_DATA = this.valData;
console.log(USER_DATA);
var scope = angular.element($("#angular-controller")).scope();
scope.$apply(function(){
scope.contacto = { varAngular: USER_DATA };
console.log(scope.contacto);
scope.angularFunction();
});
}
}
In Angular ... usually done
I hope to help you in something
Regards

Referencing the element that is calling a controller function Angularjs ( ng-change / ng-blur / ng-* ? )

The original question asked about how to determine which element called the controllers blurr function, but I didn't clarify that I was not specifically asking about ng-blur, but ng-* (ng-change, ng-focus, ng-mouseover, ng-*) in general. So, with that in mind:
How do I determine which element input is calling the blurr() and/or check() functions?
html
<body ng-app="test">
<div ng-controller="Cntrlr as cntrlr">
<form name="meta_test">
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr()" ng-change="cntrlr.check()" />
<input type="text" name='second' ng-model="cntrlr.second" ng-blur="cntrlr.blurr()" ng-change="cntrlr.check()" />
</form>
</div>
</body>
js
var app = angular.module("test", []);
app.controller("Cntrlr", ["$scope", function($scope){
this.blurr = function(){
alert("which input am I?");
alert("this is so meta.");
// ?
};
this.check = function(){
alert("this is how meta I am:");
alert(this);
}
$scope.Cntrlr = this; // see: (reference)
return $scope.Cntrlr;
}]);
You may be asking yourself "why would he want to do this?"
There are 2 reasons:
because I want to call:
$scope.user_form[meta_test.[(whatever this element is.name)]].$setValidity('spike', false);
because I'm curious. There has to be a simple way to do this.
(reference):
controller as syntax
Use this -
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr($event)" ng-change="cntrlr.check()" />
This returns the jQuery lite version of the event that causes the blurr function. Once you receive this element in your controller, you can pretty much do whatever you want with it.
The .target attribute of the event will give you the required element.
Should work
Try this:
<form name="meta_test">
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr()"
ng-change="cntrlr.check('One')" />
<input type="text" name='second' ng-model="cntrlr.second"
ng-blur="cntrlr.blurr()" ng-change="cntrlr.check('Two')" />
</form>
In JS,
this.check = function(Type){
if(Type == "One"){
//Then it is the first text box.
}else if(Type == "Two"){
//Then it is the second text box.
}
}

Resources