Getting Error: [$compile:multidir] using Angular.js - javascript

I am getting the following error while using datepicker of Angular.js.
Error message
Error: [$compile:multidir] http://errors.angularjs.org/1.4.6/$compile/multidir?p0=datepicker&p1=&p2=da…-prev%3D%22%3Ci%20class%3D%26quot%3Bfa%20fa-arrow-circle-left%26quot%3B%3E
at Error (native)
at http://oditek.in/Gofasto/js/angularjs.js:6:416
at Q (http://oditek.in/Gofasto/js/angularjs.js:69:353)
at D (http://oditek.in/Gofasto/js/angularjs.js:62:492)
at http://oditek.in/Gofasto/js/angularjs.js:68:182
at http://oditek.in/Gofasto/js/angularjs.js:118:334
at n.$eval (http://oditek.in/Gofasto/js/angularjs.js:132:452)
at n.$digest (http://oditek.in/Gofasto/js/angularjs.js:129:463)
at n.$apply (http://oditek.in/Gofasto/js/angularjs.js:133:236)
at g (http://oditek.in/Gofasto/js/angularjs.js:87:376)
I am explaining my code below.
<div class="input-group bmargindiv1 col-md-12">
<span class="input-group-addon ndrftextwidth text-right" style="width:180px">Date :</span>
<datepicker date-format="dd-MM-y" button-prev='<i class="fa fa-arrow-circle-left"></i>' button-next='<i class="fa fa-arrow-circle-right"></i>'>
<input type="text" name="birthdate" class="form-control" ng-model="date" placeholder="Add date" />
</datepicker>
</div>
I have already included the 720kb.datepicker module and added the respective css and js files.Still i am getting the above type of error.
Please help me to resolve this error.

Angularjs is exporting a url to explain the error message which is
https://docs.angularjs.org/error/$compile/multidir?p0=datepicker&p1=&p2=da%E2%80%A6-prev%3D%22%3Ci%20class%3D%26quot;fa%20fa-arrow-circle-left%26quot;%3E
in your case and explanation locates your prev button definition.
Multiple directives [datepicker, da…-prev="{3}] asking for {4} on: {5}
Description This error occurs when multiple directives are applied to
the same DOM element, and processing them would result in a collision
or an unsupported configuration.
To resolve this issue remove one of the directives which is causing
the collision.
Example scenarios of multiple incompatible directives applied to the
same element include:
Multiple directives requesting isolated scope. Multiple directives
publishing a controller under the same name. Multiple directives
declared with the transclusion option. Multiple directives attempting
to define a template or templateURL.
Most probably button-prev or button-next is overlaping with datepicker directive.

Related

error in getting value from input that have ngIf directive

I get an exception Error TypeError and Error Context when the submit button is clicked. If I will delete the ngIf directive It will work as excepted, The Full StackTrace:
PlayerNameFormComponent.html:8 ERROR TypeError: Cannot read property 'value' of undefined
at Object.eval [as handleEvent] (PlayerNameFormComponent.html:8)
at handleEvent (core.js:13547)
at callWithDebugContext (core.js:15056)
at Object.debugHandleEvent [as handleEvent] (core.js:14643)
at dispatchEvent (core.js:9962)
at eval (core.js:12301)
at SafeSubscriber.schedulerFn [as _next] (core.js:4343)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:240)
at SafeSubscriber.next (Subscriber.js:187)
at Subscriber._next (Subscriber.js:128)
PlayerNameFormComponent.html
<form (ngSubmit)="onSubmit(firstPlayer.value, secondPlayer.value)"> // The line that throws the exception
<div class="input-field col s6">
<label for="firstPlayer">First Player Name</label>
<input #firstPlayer id="firstPlayer" name="firstPlayer" type="text" class="validate">
</div>
<div *ngIf="isMultiplePlayers" class="input-field col s6">
<label for="secondPlayer">Second Player Name</label>
<input #secondPlayer id="secondPlayer" name="secondPlayer" type="text" class="validate">
</div>
<button type="submit" class="waves-effect waves-light btn">Start</button>
</form>
PlayerNameFormComponent.ts
export class PlayerNameFormComponent {
isMultiplePlayers = true;
public onSubmit(firstPlayer: string, secondPlayer: string) {
console.log(firstPlayer);
console.log(secondPlayer);
}
}
EDIT:
I changed my form tag to - <form (ngSubmit)="onSubmit(firstPlayer?.value, secondPlayer?.value)"> and now its print to console the firstPlayer input value and instead of secondPlayer value its prints null
Thanks for any kind of help :)
Template reference variables can be accessed anywhere in template, so the docs state clearly. This article is very helpful to understand what happens with structular directives, in this case your *ngIf.
What happens with the *ngIf is that it creates it's own template, so your template reference is accessible inside the template, the template created by *ngIf and only in that scope.
Here's excerpt from the website:
Sample code that throws error:
<div *ngIf="true">
<my-component #variable [input]="'Do you see me?'>
</div>
{{ variable.input }}
The reason for this is the ngIf directive - or any other directive used together with a star (*). These directives are so called structural directives and the star is just a short form for something more complex. Every time you use a structural directive (ngIf, ngFor, ngSwitchCase, ...) Angular's view engine is desugaring (it removes the syntactical sugar) the star within two steps to the following final form (using the previous ngIf as an example):
<ng-template [ngIf]="true">
...
</ng-template>`
Did you notice? Something extraordinary emerged out of the previous HTML containing the structural directive - the ng-template node. This node is the reason for limiting the scope of the template reference variable to exactly this inner DOM part only - it defines a new template inside. Because of limiting a variable to its defining template any variable defined within the ng-template (and this means within the DOM part of the ngIf) cannot be used outside of it. It cannot cross the borders of a template.
But how to solve your underlying problem, i.e getting the values... You almost have a template-driven form set up already, so you could do that, or then go the reactive way :)
Your problem doesn't come from your *ngIf. Try to remove temporary the error, using Elvis operator:
onSubmit(firstPlayer?.value, secondPlayer?.value)
Or you can make sure into your onSubmit that the HTML element firstPlayer and secondePlayer return HTMLObject.
Into your component, do this:
onSubmit(firstPlayer, secondPlayer) {
console.log(firstPlayer, secondPlayer);
}
And into your HTML template, change the (ngSubmit) line with:
<form (ngSubmit)="onSubmit(firstPlayer, secondPlayer)">
If the result is correction you get ...
<input id="firstPlayer" name="firstPlayer" type="text" class="validate">
...
... into the console.
If it is really undefined, use [ngModel]="firstPlayer" and check if the error still occurs.
You can also just the line as given below to get it working if you don't want to go to the reactive forms approach as pointed by #AT82.
<div *ngIf="isMultiplePlayers" class="input-field col s6">
to
<div [hidden]="isMultiplePlayers" class="input-field col s6">
Try to avoid *(star) directives which cause these errors due to structural changes they do in the DOM.

EXCEPTION: Template parse errors in angular 2.0 behaving differently

A sample application in angular 2.0 using typescript is working perfectly in plnker (Link Here). But when the same thing is running using VS 2013, I am getting an error like below
EXCEPTION: Template parse errors:
Can't bind to 'ngmodel' since it isn't a known native property ("<label>Name:</label>
<input [ERROR ->][(ngmodel)]="yourname" placeholder="Enter a name here">
<hr>
<h1 [hidden]="!yourname">Hello {{yourname}}!</h1>
"): HelloWorld#1:8
If I remove [(ngmodel)]="yourname" I am getting the HTML page atleast. Can anyone help with this??
You should use ngModel instead of ngmodel:
<input [(ngModel)]="yourname" placeholder="Enter a name here">

How would I create something similar like this in AngularJS

Having a hard time grasping AngularJs.. How would you build something like this simple textfields and animations in AngularJS? I had been looking into using directives but it just isn't adding up to me much. I had been trying to base this from what I learned online but was not having much luck
http://codepen.io/yusufbkr/pen/RPBQqg
HTML:
<div class="materialContainer">
<div class="title">LOGIN</div>
<div class="input">
<label for="name">Username</label>
<input type="text" name="name" id="name">
<span class="spin"></span>
</div>
<div class="input">
<label for="pass">Password</label>
<input type="password" name="pass" id="pass">
<span class="spin"></span>
</div>
<div class="button login">
<button><span>GO</span> <i class="fa fa-check"></i></button>
</div>
Forgot your password?
<div class="title">REGISTER</div>
<div class="input">
<label for="regname">Username</label>
<input type="text" name="regname" id="regname">
<span class="spin"></span>
</div>
<div class="input">
<label for="regpass">Password</label>
<input type="password" name="regpass" id="regpass">
<span class="spin"></span>
</div>
<div class="input">
<label for="reregpass">Repeat Password</label>
<input type="password" name="reregpass" id="reregpass">
<span class="spin"></span>
</div>
<div class="button">
<button><span>NEXT</span></button>
</div>
just use the codepen link ( http://codepen.io/yusufbkr/pen/RPBQqg ), stackoverflow won't let me input the rest of the code...
Thanks! Any help would be incredible
I'm just learning Angular myself. From what I know, you're on the right track to be thinking of directives for swapping out interactive parts of the DOM. I suspect you'll also be needing ui-router for dealing with the widget outcomes (I hear it's the industry standard, vs the built-in ngRouter).
I'm partly writing this out to make sure I understand it, so I hope other, more knowledgeable people will come by and answer any questions you have about it (or point out where I'm misundertanding something.)
So you bring the webpage into the Angular world by, for instance, making the <html></html> tags into <html ng-app="yourApp"></html>. The unchanging html that will be the same on every view is in the index.html file. Put the html for the boxes is in another html file, say box.html. On the index.html file in the place where you want to have your boxes appear, put <div ui-view></div>. The ui-view connects to ui-router. Down at the bottom of the index.html right before closing the body tag, put
<script src="lib/angular/angular.js"></script>
<script src="lib/angular-ui-router/release/angular-ui-router.js"></script>
<script src="app/app.js"></script>.
In app.js, you put something like,
angular.module('yourApp', [
'yourApp.box',
'ui.router'
])
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
$urlRouterProvider
.otherwise('/signin/child');
$stateProvider
.state('box', {
url: '/signin',
templateUrl: 'app/box/box.html',
controller: 'BoxController'
})
.state('box.child', {
url: '/child',
template: '<span>{{ definedProperty }}</span>'
});
})
});
Starting at the top, you name angular, call its module function, and give it the parameters ('theNameYouChose', ['dependencies','required'])
In the config bit there, you're telling it about dependencies config needs. $stateProvider and $urlRouterProvider are ui-router things, and $httpProvider is, I believe, an angular thing that is still necessary.
In the urlRouterProvider, you're providing the default address the website goes to: in this case it happens to be a template within a template, /signin from the signin state, and /child from the specifics pasted into signin
In the states, you are giving names and properties to the URLs that will be part of your app: like, if someone goes to index.html/signin, the 'signin' state is summoned.
The template within a template might be how you'd get the box variability that you're looking for. In box.html you will have another <div ui-view></div> and that's where the varying thing described in 'signin.child' gets put in.
box.html is also the place you put your specially created html tags, the ones you will make with the directive. I'll talk through those below.
The parent template, 'signin', talks about BoxController. Let's say you built that in box.js. It would look like this:
angular.module('yourApp.box', [])
.controller('BoxController', function ($scope) {
$scope.definedProperty = 'reRegPass',
$scope.arrayOfObjects = [{prop: 'red'},{prop: 'blue'}]
})
.directive('specificBox', function(){
return {
restrict: 'EA',
templateUrl: 'app/box/box-guts.html',
replace: true,
scope: {
source: '='
},
link: function(scope, element, attribute) {
element.on('click', function() {
alert('Functionality in specificBox is working');
}
}
}
});
The first line is again summoning angular module, and then naming it: note we already listed this, 'yourApp.box', as a requirement in app.js. Then we have the controller-naming function, and the appearance of specific properties in their $scope.
The directive is taking the more useful of the two forms a directive can take. They can either return functions (with signatures like the one in .link), or they can return objects that describe new HTML entities. This one is named specificBox, which Angular will translate into <specific-box></specific-box>. This object (technically called a 'directive definition object') can be translated into HTML tags because of the restrict property... 'E' is for element. 'A' is for attribute. I don't know how something that can be an element could also be an attribute, but having both options works, so I'm going with it. (Maybe for your various signin boxes you want a directive that has just 'A' to make new types of attributes.)
You put these specifically-crafted tags into box.html, and everything in box-guts.html will be between those tags... In fact, replacing those tags because of the replace: true.
The .link property is where you would put a function that would do something interesting to that element; turn it red if clicked, whatever. I have an alert example. Uses jQuery Lite for events.
The .scope property is odd. I believe if left off, the specific-box stuff would have the same controller as box (ie, BoxController), with box's scope and dependencies. But here, instead, we're making an isolate scope. box-guts will not depend on anything or have access to anything built before. How will it get interesting changeable data, then..? Every property in the scope object becomes an attribute on specific-box.
The '=' means that you will pass it objects from somewhere, and they will have 2-way data binding (changes made in box-guts will be reflected in the object collection in your app). Other options are '#', one-way data binding, which means you're passing box-guts a string or something that, if it changes in the DOM, you don't care to reflect in your app; or '&' to give it a function from a controller somewhere else in your app.
So ultimately, in box.html, you will have something like
<div class="box-holder">
<div ui-view></div>
<specific-box source="thing" ng-repeat="thing in arrayOfObjects"></specific-box>
</div>
Like I said above, ask questions and maybe we can sort this out.

AngularJS ngMessages can't bind to $index expression

I am building an Angular form that needs repeatable form elements inside an ngRepeat.
<form name="form">
<div ng-repeat="x in [1,2,3,4]">
<input name="something_{{$index}}" ng-model="hi" required>
<div ng-messages="form.something_{{$index}}.$error">
<ng-message="required">This is required</ng-message>
</div>
</div>
<pre>{{form | json: 4}}</pre>
</form>
Angular now supports dynamically declared input names so that you don't have to do something like:
<div ng-repeat="x in [1,2,3,4] ng-form="repeated-form"></div>
And you can use {{$index}} inside the ngRepeat to declare items dynamically. But this doesn't seem to work with ngMessages, which throws an error when I try to bind the index into it.
i.e. this:
<div ng-messages="form.something_{{$index}}.$error">
throws this:
Error: [$parse:syntax] Syntax Error: Token '{' is an unexpected token at column 16 of the expression [form.something_{{$index}}.$error] starting at [{{$index}}.$error].
How can we dynamically declare which property on the form to watch, if ng-messages can't watch the form value that is declared with its {{$index}}?
PLNKR: http://plnkr.co/edit/4oOasbtffTgKqmxcppUG?p=preview (check console)
ng-messages="form['something_' + $index].$error"
Should work. I generally wouldn't put {{ }} in any of the ng directives because most of the ng directives execute with priority level 0 (including the {{ }} directive, ngBind). Also, the ng directives all use $evaluate on their argument, so they look at variable values in the scope by default.
Priority 0 for multiple directives on the same element means that Angular can't guarantee which directive will be applied first. Because of that, it is generally best to avoid using ngDirectives together as behavior can vary. ngIf is an exception as it executes with priority 600 (which is why directives aren't evaluated for an ng-if element not currently in the DOM no matter what).
<div ng-repeat="x in [0,1,2,3]">
<input name="something_{{$index}}" ng-model="hi" required>
<div ng-messages="form['something_' + $index].$error">
<ng-message="required">This is required</ng-message>
</div>
</div>
http://plnkr.co/edit/k5nzkpkJwSuf5dvlMMZi?p=preview

Multiple view models break knockout.js

I'm trying to use multiple view models as suggested in the documentation and in this other answer.
I'm getting an error in the console complaining about a variable not being defined:
Uncaught ReferenceError: Unable to process binding "foreach: function (){return seals }"
Message: seals is not defined
Reproduction online
HTML
<!-- ko foreach: seals -->
<div class="form-group">
<label for="seal" class="col-xs-2 control-label" data-bind="text: 'Seal ' + name"></label>
<div class="col-xs-8">
<input type="text" class="form-control" data-bind="attr: {name: 'seal' + formName}" />
</div>
</div>
<!-- /ko -->
JS
ko.applyBindings(demo, document.body);
ko.applyBindings(addEquipmentModel, document.getElementById('whatever'));
The problem is here:
ko.applyBindings(demo, document.body);
You are applying a model to document.body, so it's going to try and parse and bind the whole document. When it gets to the part with:
<!-- ko foreach: seals -->
You get an error because the demo model doesn't have a seals property.
In practice, you don't want the elements that you are binding to overlap. In other words, don't bind one model to a child element of an element that is bound to another model. They should be siblings, or cousins. Not direct descendants.
If you need several viewmodels nested in your view, or even in a child-parent relation, you should consider using Knockout components for that. Another possibility aside from that is to use apply(this) in your main viewmodel to the other viewmodels 'class' so your main viewmodel sort of inherits the functionality and properties of the referred model. This will, though, lead to problems if you have name concurrencies in your viewmodels.

Categories