Wrapping angular typeAhead in separate directive - angularjs

My goal was to wrap angular-ui typeAhead directive into easily re-usable component, that could be used like this:
<input my-person-lookup="myModel.personId" ></input>
I've achieve this by writing my custom directive, and specifying static template for typeahead. Here is Plunker
Now, I would like to build this template dynamically, and then compile it:
var html = '<input type="text" ng-model="directiveModel.selectedPerson" typeahead=" p as p.name for p in people" typeahead-min-length="1" typeahead-wait-ms="200" typeahead-editable="false" placeholder="type p"></input>';
element.replaceWith($compile(html)(scope));
Unfortunately this approach didn't work Plunker.
Could anyone tell me what I'm doing wrong?

Just move your data to the wrapping controller and remove your isolated scope.
Plunker
Plunker2

Related

ng-messages aren't displayed in custom directive

I created a custom directive which is used to access the id of the form, to display messages if same validation failed.
directive Code
<div>
<md-input-container>
<label class="inputLabel" translate>amount</label>
<input ng-model="order.amount" name="amount" type="text" required
max="availableAmount"
ng-disabled="disabled" ng-currency flex/>
<ng-messages flex for="dataForm.amount.$error" ng-if="dataForm.amount.$dirty">
<ng-message when="max">max reached</ng-message>
</ng-messages>
</md-input-container>
</div>
usage:
<form id="dataForm">
<custom-directive></custom-directive>
</form>
It seems like I can not access the form. Or angularmessage can not handle the different scoping.
Has anyone the same problem or an idea?
Thank you
fyi.: I have found the following post, but I didn't think that i have the same problem as that guy.
angularjs ngMessages inside directive
I use Angular 1.4.8;message 1.4.8 and angular material 1.0.4
If directive have an isolated scope, than it will not be able to access the form controller object of the ng-form directive.
Angular enables multiple canonical forms, so you can simply wrap your input inside of your directive with a form / ng-form.

Angular transcluding attributes

I'm looking to pass through most of the attributes on my directive, like so:
<my-directive name='test'
type='select'
ng-required
ng-options="v for (k,v) in types" />
Where name and type are specific to the directive and everything else is passed through to the directive template:
<div class='parent'><input name="hello" ng-transclude /></div> - the input should be given an ng-required and ng-options.
How do I do this?
You can use the link function of the directive, you can inject to it a list of the attributes you put in the directive and apply it the the element you need inside the directive, nite that if you use directive attributes you will have to use $compile to let angular comprehend it is a directive and not just an attribute

AngularJS file upload is not working when we use ng-change

In file upload ng-change is not working as expected in angularJS
<input type="file" ng-model="fileUpload" ng-change="setFiles(this) /"
JS:
$scope.setFiles=function(element){
console.log(element.files);
}
Here element.files is undefined
But if i chage the ng-change to onchange it's working.
<input type="file" ng-model="fileUpload" onchange="angular.element(this).scope().setFiles(this)"/>
JS:
$scope.setFiles=function(element){
console.log(element.files);
}
Here i'm getting the element.files object.
Why it is working in onchange not in ng-change?
Angular doesn't seem to support binding for <input type="file"..../>. It seems like you have to create a directive... full details here. You can also try this library
<input type="file" id="file_upload_id_here" style="width:55%" name="file" onchange="angular.element(document.getElementById('file_upload_id_here')).scope().getFileDetailsCandidate(document.getElementById('file_upload_id_here'))" />
use like the above, some times the root scope is switchesm it cannot revert it current scope, on that this functionality will not works, so put your current document object like the above

How to prevent transcluding directive to create new child scope for the form directive?

I have a problem with directive transclude and the form directive. As you may know, the form will end up in the "scope" if you add the "name"-property to the form tag, then you can check for form validation and so on.
My problem start when i put the form tag in a directive that uses transclude. I'm aware of how to deal with this problem with two-way data binding, as mention here https://stackoverflow.com/a/14484903/1029874 -- "use an object instead of a primitive"
But my form ends up in the transcluding directives scope. Here is an example of what i want to do.
<div ng-controller="appCtrl">
<widget>
<widget-header>{{model.property}}</widget-header>
<widget-body>
<!-- The form will end up in "widget-body":s scope instead of appCtrl:s scope -->
<form name="appForm" ng-submit="submit()">
<input type="text" required ng-model="model.property" />
<input type="submit" value="submit" />
</form>
</widget-body>
</widget>
</div>
And here is the fiddle, http://jsfiddle.net/WLksJ/1/
Is there a way that I can get around this behavior?
Thanks!
An interesting question, but a problem that's easily avoided by using
<form name="appForm" ng-submit="submit(appForm.$valid)">
and checking the parameter in the submit function.
http://jsfiddle.net/udMJ7/
Another (perhaps better) option is to use this which is set to the scope of the last controller (in this case the form controller, which we want)
$scope.submit = function(){
if(this.appForm.$valid){
//post the form!!
}
};
http://jsfiddle.net/udMJ7/1/

AngularJS - Model not updating on selection of radio button generated by ng-repeat

I am generating a bunch of radio buttons using ng-repeat, and then trying to update a model when one of them is selected. This doesn't appear to be working.
The same markup works just fine when the radio inputs are hardcoded as opposed to being generated by ng-repeat.
This works:
<input type="radio" ng-model="lunch" value="chicken" name="lunch">
<input type="radio" ng-model="lunch" value="beef" name="lunch">
<input type="radio" ng-model="lunch" value="fish" name="lunch">
{{lunch}}
This doesn't:
<input type="radio" ng-model="lunch" ng-repeat="m in meat" value="m" name="lunch">
{{lunch}}
See jsfiddle showing both here: http://jsfiddle.net/mark_up/A2qCS/1/
Any help would be appreciated.
Thanks
<div ng-controller="DynamicCtrl">
<input type="radio" ng-model="$parent.lunch" ng-repeat="m in meat"
ng-value="m" name="lunch">
{{lunch}}
</div>
Should do the trick.
As I understand it, ng-repeat creates its own $scope. so you need to refer to the $parent $scope; Yes, AngularJS is tricky. Also you need to change the value to ng-value too.
the above issue was discussed here
That happens because ng-repeat creates a new scope. Basically, each <input> is creating a selectedOption value on its own inner scope. To work around that, create a new container object for that value. For example, you could declare in your controller:
$scope.data = {selectedOption: x};
And then in your template, use ng-model="data.selectedOption"
in this way, ng-model gets updated .. :)
this is tricky
Just need to replace value with ng-value

Resources