I have the following problem with angular custom directives. I have a modal dialog that gets filled with input elements. These input elements get filled using ng-repeat angular directive like this
<div ng-repeat="item in params">
<label>{{item.nombre}}{{item.valor}}</label>
<div class="input-group" ng-if="item.tipo=='DATE'">
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
<input type="text" name="{{item.nombre}}" class="form-control reportesFechas" ng-model="item.valor"
data-custom-datepicker data-date-format="dd/mm/yy" id="{{item.nombre}}">
</div>
</div>
data-custom-datepicker is my custom attribute. The params model gets filled via a service call to a java backend like this
appbsReportsParamsService.query({
q: "idReport="+id
}, function(data){
$scope.params = data.content;
})
The service call works OK because the final HTML is "correct" in terms of inputs gets generated. However data-custom-datepicker doesn't get applied.
This is the HTML "ng-repeat" portion being generated:
<div class="input-group ng-scope" ng-if="item.tipo=='DATE'">
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
<input type="text" name="fecDesde" class="form-control reportesFechas hasDatepicker ng-pristine ng-valid ng-touched" ng-model="item.valor" data-custom-datepicker="" data-date-format="dd/mm/yy" id="fecDesde">
</div>
<div class="input-group ng-scope" ng-if="item.tipo=='DATE'">
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
<input type="text" name="fecHasta" class="form-control reportesFechas hasDatepicker ng-pristine ng-valid ng-touched" ng-model="item.valor" data-custom-datepicker="" data-date-format="dd/mm/yy" id="fecHasta">
</div>
So basically I want to know how to apply the directive after a async service call to populate the model.
Try adding $scope.$apply() in your service success call after $scope.params = data.content.
Because your params service query is running outside of the $scope in Angular, doing the $apply, will force update the $scope.
See if that helps.
appbsReportsParamsService.query({
q: "idReport="+id
}, function(data){
$scope.params = data.content;
$scope.$apply();
});
Ok, the problem was I was running the directive code under "compile" phase. I change it to "post" phase, now everything works ok. The problem is the Angular workflow (not the problem, but where my misconception was). This post helped me understand.
Angular directives - when and how to use compile, controller, pre-link and post-link
Related
iam using input helper in ember for binding attributes value
<div class="form-group profile-desa-component-form-group">
<label class="col-sm-4 control-label">{{t 'field.alamat'}}</label>
<div class="col-sm-8 no-padding">
{{#if editMode}}
{{input class="form-control editonly btn-no-corner" key-press="onKeyPressShowPanel" type="text" value=alamat}} <- this is my input helper
{{else}}
<input readonly class="form-control btn-no-corner readonly" type="text" value={{alamat}}>
{{/if}}
</div>
{{backend/pop-up-form title="Isikan alamat lengkap kantor desa dan kelurahan"}}
</div>
i just want to pass an event object from key-press = onKeyPressShowPanel to the controller so i can use event.target to manipulate some element via jquery snipet. this is my onKeyPressShowPanel action in controller
onKeyPressShowPanel(event){
this.debug(event);
},
unfortunately the event that i pass is a value that come from value = alamat.
how to get an event.target from event on input helper so i can manipulate some element using jquery. Any answers would be helpfull for me.. thank you :)
You can try the below code to get jquery.Event object,
{{input class="form-control editonly btn-no-corner" keyPress=(action "onKeyPressShowPanel") type="text" value=alamat}}
manipulate some element using jquery -Generally is not good but it depends on your case
Within multiple forms in my app, I am trying to use the same directive which is an email input field complete with validation (it sources its value from a list of recently used emails but that is not pertinent to this question). Because the form in which the directive is used is different depending on where I use it, the ng-messages attribute needs to be dynamically rendered.
I have managed to get ng-messages to dynamically set itself, but it is not working as expected. Here is the code:
form.html
<form name="joinForm">
<rt-recents-menu ng-model="vm.roomName"/>
</form>
directive.coffee
recents = angular.module 'rtRecents', ['ionic', 'ngMessages']
.factory('rtRecentsService', require './recentsService')
.directive('rtRecentsMenu', (rtRecentsService, $ionicActionSheet) ->
restrict: 'E'
template: require './recentsMenu.html'
scope:
ngModel: '=?'
require: ['?ngModel', '^form']
transclude: false
replace: false
link: (scope, element, attrs, ctrls) ->
ngModel = ctrls[0]
formCtrl = ctrls[1]
scope.formName = formCtrl.$name
module.exports = recents.name
directive.html
<div class="email-line">
<input type="email"
name="roomName"
required
ng-model="ngModel"
ng-keydown="onKeyDown()"/>
<div id="email-error-messages" ng-messages="{{formName}}.roomName.$error" multiple role="alert">
<div ng-message="required" class="warn" translate>VALIDATION.EMAIL_REQUIRED_ERROR</div>
<div ng-message="email" class="warn" translate>VALIDATION.EMAIL_INVALID_ERROR</div>
</div>
</div>
In my case, I have a that displays each of the returned rows from a db query. And each row had its own form within this repeat loop.
I ran into two problems:
The ngMessage errors didn't display correctly because they didn't seem to be tied to the right fields/form.
I couldn't disable the "save" button per-form. The $invalid didn't seem to work.
Here's what works (trimmed decorators, etc so you only see the essential points):
<div ng-repeat="row in rows | orderBy: 'sortBy'"
ng-init="formName = 'siteEdit' + row.id">
<form name="{{formName}}" ng-submit="view.startSave(row.id)">
<!-- I have "control" buttons at the top of my form to save, cancel, etc. here are the two related to saving -->
<span class="glyphicon glyphicon-save pull-right q-palette-color-2" ng-disabled="view.isPageBusy()"
ng-show="! this[formName].$invalid" ng-click="view.startSave(row.id)" title="Save"/>
<span class="glyphicon glyphicon-ban-circle pull-right q-palette-accent-2"
ng-show="this[formName].$invalid" style="padding-left:10px;cursor: pointer; cursor: hand;" data-toggle="tooltip" title="Correct Errors To Save"/>
<label for="siteName{{row.id}}"> Name:</label>
<input id="siteName{{row.id}}"
class="form-control input"
type="text"
placeholder="name"
ng-disabled="view.isPageBusy()"
ng-model="row.name"
name="name"
required />
<div ng-messages="formName.name.$error">
<div ng-message="required">This field is required</div>
</div>
.....
</form>
</div>
Key points:
ng-init in the ng-repeat builds the formName variable.
form validation for save/etc uses this[formName].$invalid
Field validation is referenced in the format of formName..$error
Something to note:
I couldn't get the ng-disable to actually disable the "button" based on it being invalid or not (the ng-click executed no matter what, maybe because I didn't use <button> but used <span> w/ glyphicon). So I opted to have one displayed when you can save, the other displayed when you can't. Works better this way since the person can visually see they can't save, and if they hover over they'll see they need to correct the form first.
I have problem with angular material.
I want to use Angular Material md-select directive with dynamic text in label. It seams that their directive creates copy of the html label text and put in in its span so after scope value is updated it is updating value in hidden label but not in their span (it is updating in after you open and close select list). Is it a bug or I am doing something wrong? If it is a bug does anybody see a nice way to fix it?
Thanks in advance!
JS:
angular.module('myApp', ['ngMaterial'])
.controller('MyController', function ($scope, $timeout) {
$timeout(function(){
$scope['select_n_letter'] = 'Lorem ipsum';
}, 500);
})
;
;
HTML:
<body ng-app="myApp">
<div ng-controller="MyController" style="padding-top: 50px">
<form name="a_form">
<md-input-container>
<label>{{select_n_letter}}</label>
<md-select
required
name="letter"
ng-model="letter"
>
<md-option value="option">selected</md-option>
</md-select>
</md-input-container>
</form>
</div>
Plunker
EDIT
To see which span I mean please check the Plumker preview and see compiled directive HTML which looks like below:
<md-select required="" name="letter" ng-model="letter" class="ng-pristine md-default-theme ng-invalid ng-invalid-required ng-touched" tabindex="0" aria-disabled="false" role="combobox" aria-expanded="false" id="select_3" aria-required="true" aria-invalid="true">
<md-select-value class="md-select-value md-select-placeholder" id="select_value_label_0">
<span>/* text should goes here */</span>
<span class="md-select-icon" aria-hidden="true"></span>
</md-select-value>
</md-select>
One possible solution is to show two identical md-select's ( apart from their label ). And use ng-show to switch between them.
Another possibility, use a directive containing md-select inside.
Switch it on and off with ng-if with a different label as an input.
Hope this helps
I have two controllers in my AngularJS apps. In my first Controller, I have an input/dropdown field, which value I want to use in second nested controller for each ng-Change. For example,
My Code (HTML) ::
<body ng-app="myApp" ng-controller="DropdownCtrl">
<input type="text" class="form-control" ng-model="dt" ng-change="changeDate(dt)" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
<div class="row" ng-controller="MainCtrl">
<!-- other code -->
</div>
</body>
Now what I want to do, when ng-Change is happening, I want to use changeDate(dt) function's value in MainCtrl
In order for a parent controller to communicate with a child controller, the parent controller should use $scope.$broadcast('changedValue', dt);
This will broadcast to all children controllers the new value of dt. The childController should then listen for the change with the following code:
$scope.$on('parent-message', function (event, dt) {
//you can now use dt in the child controller to do whatever it is you wanted
});
This is especially nice when using routeProviders and ng-view
Here is a great tutorial that explains this all really well:
I have the following markup. The function isn't called when you click on the icon and there are no errors logged to the console.
Online search hasn't shown others with this issue, so either it's a feature of the 'input append' markup or I've got something basic wrong that I'm just not seeing.
I'm using bootstrap 2.3 and angularjs 1.2.13
<div class="input-append input-block-level">
<input type="text" name="myFieldName" ng-model="model[field]"
class="input-block-level ng-pristine ng-valid ng-valid-required"
placeholder="My Field Name" ng-required="false">
<a class="btn add-on" ng-click="aCtrlFunc('my field name')">
<i class="icon-search"></i>
</a>
</div>
The form works, the model is updated as expected when typing into the field and on form submit. Why doesn't this button click work?
update
Mystery solved. It's a scope issue, like this one: https://stackoverflow.com/a/16489532/149060
The form fields are generated by a directive who's templates include ngRepeats. I didn't think of it because I didn't think it was using an isolate scope.