How to set modelValue in Angular formly using custom template - javascript

I have create custom template to add todo list in angular formly. jsbin Link
I'm trying to add required validation but its not working. I have added validators to check. But viewValue, modelValue contains value in input field. Is there are any way to set modelValue in validator with actual model.
return [
{
className: 'col-sm-12 col-md-12 col-lg-12',
key: 'todoList',
type: 'todolist',
templateOptions: {
type: 'text',
label: 'Add todo list',
placeholder: 'Enter todo list'
},
validators: {
tagLength: {
expression: function(viewValue, modelValue) {
var value = modelValue || viewValue;
console.log(modelValue)
console.log(viewValue)
//return value.length > 0;
},
message: '"Altest 1 Operation is required"'
}
}
}
What i'm exactly trying to achive is, if todolist is empty then submit button should be disabled.
Thanks in advance.

This is completely unnecessary. All you have to do is set the ng-show in the submit button. No validators are needed. Just tested it on your jsbin link and it works as expected. Please mark this as the correct answer.
ng-show="vm.model.todoList.length > 0" OR
ng-show="vm.model.todoList" (since it will be false if empty/undefined)
Validators are to validate the input on THAT field, not for other fields/buttons.

Related

Angular 7: How to reset few checkboxes (generated dynamically using *ngFor) to it's previous state only click of a button

I have a child component which consists of 3 checkboxes (generated dynamically using ngFor) and an Apply and Cancel button.
Selector tag for the child is added in the parent's template. Parent component accesses this child component using #ViewChild and calls the present() method exposed by the child component with an object as argument as below which consists of checked state of the checkboxes.
Every time when modal is displayed, present() method is getting called. For the first time, UI/checkboxes is getting updated/checked as the values sent by parent. But, in the subsequent calls to present(), even though options.checked value is getting updated as expected in the ts file, this is not getting reflected in the UI. Every time the modal is displayed, I want checkbox to be checked or unchecked based on the value sent by the parent in present() method. Need help. Thanks in advance
parent.component.ts:
#ViewChild(childModalComponent) childModalComponent: ChildModalComponent;
onBtnClick() {
this.childModalComponent.present({
checkbox1: true,
checkbox2: false,
checkbox3: false
});
}
parent.component.html:
<feature-child-modal></feature-child-modal>
child.component.ts:
#ViewChild('childModal') childModal: ElementRef;
ngOnInit() {
this.options = [
{
label: 'label1',
value: 'value1',
checked: false,
},
{
label: 'label2',
value: 'value2',
checked: false,
},
{
label: 'label3',
value: 'value3',
checked: false,
},
];
}
present(optionsState: CompressTransactionType) {
this.options.forEach(item => {
if(item.value == "value1"){
item.checked = optionsState.checkbox1;
}
if(item.value == "value2"){
item.checked = optionsState.checkbox2;
}
if(item.value == "value3"){
item.checked = optionsState.checkbox3;
}
});
this.childModal.nativeElement.present();
}
dismiss() {
this.childModal.nativeElement.dismiss();
}
child.component.html:
<div *ngFor="let option of options">
<input
type="checkbox"
[value]="option.value"
(change)="onOptionsSelectChanged($event)"
[checked]="option.checked" />
</div>
try passing the array object here option instead of $event. Have a look in this url..
https://stackblitz.com/edit/angular-ivy-wifdeg

How to solve "of undefined" problem of a service?

I am calling service in Angular7 at every dropdown option change. But when I change selected option on dropdown I am getting getAllByCountryId of undefined error.
Here is function that calling http service:
countryOnChange(countryId: Guid) {
this.cityService.getAllByCountryId(countryId).subscribe(
res => {
if (res.code === ResponseCode.success) {
res.dataList.map(item => {
this.cities.push({
value: item.id.toString(),
label: item.dataValue
});
});
if (this.formComponent !== undefined) {
this.formComponent.form.controls['cityId'].patchValue(this.cities);
}
}
},
err => {
this.error = true;
});
}
Here is the HTML code that calling above function on every dropdown option change:
<ng-container *ngSwitchCase="'dropdown'" class="col-md-12">
<ng-select [ngClass]="'ng-select'" [options]="input.options" [formControlName]="input.key" [id]="input.key" (selected)="input.onChange($event.value)"></ng-select>
</ng-container>
input.onChange($event.value) and countryOnChange is connected at the backend.
Here is how to call countryOnChange function:
const dropdown2 = new InputDropdown({
key: 'countryId',
label: '',
onChange: this.countryOnChange,
options: this.countries,
value: '',
required: true,
order: 3
});
Error http://prntscr.com/ovjxe7
How can I solve this problem?
I think [ngModel] is needed:
<select [ngModel]="selectedValue" (ngModelChange)="onDropdownChange($event)"
class="form-control">
<option *ngFor="let category of categorylist" [ngValue]="category.id">
{{category.Description}}</option>
</select>
refer to: Angular 2 How to bind selected id in Dropdownlist with model?
getAllByCountryId of undefined error means you are getting this.cityService as undefined.
Check with which this context your function is binding when you are creating the InputDropDown. May be you need to define it like :-
const dropdown2 = new InputDropdown({
key: 'countryId',
label: '',
onChange: this.countryOnChange.bind(this),
options: this.countries.bind(this),
value: '',
required: true,
order: 3
});
Hope this helps.

Capturing Click Event to Pass Into Function in Angular App

I have set up some filters a user can click on in order to filter a list display in my Angular app. The relevant code in my view looks like this:
<md-checkbox *ngFor="let option of categoryFilters.options" [(ngModel)]="option.value" (click)="filterByCategory($event)">
{{option.label}}
</md-checkbox>
You'll notice that I have a "filterByCategory()" function above. What I want to do with that is filter the list according to the value that the user clicks on from the md-checkbox list. So far I haven't been able to capture that value.
I've tried this in my component:
public filterByCategory(option) {
console.log('Category filter ' + option + ' was clicked');
}
But that just prints the mouse event to the console:
'Category filter [object MouseEvent] was clicked'
I also tried using the two-way-bound value, like this:
public filterByCategory(option) {
console.log('Category filter ' + this.option.value + ' was clicked');
}
But that returns 'undefined'.
By the way, the options I'm trying access the values of here look like this in my component:
private categoryFilters = {
enabled: true,
options: [
{ toolbarLabel: 'A', label: 'Option A', value: false },
{ toolbarLabel: 'B', label: 'Option B', value: false },
{ toolbarLabel: 'C ', label: 'Option C ', value: false }
],
text: null
};
What can use to actually get the value that was clicked on, in order to pass that into the filter function?
Try this.
(click)="optionClicked(option)">
optionClicked(option) {
console.log(option.value)
}
UPDATE:
You can also try this:
<md-checkbox *ngFor="let option of categoryFilters.options"
[(ngModel)]="option.value" (change)="filterByCategory(option.label, $event)">
{{option.label}}
</md-checkbox>
filterByCategory(value, checked) {
if(checked) {
console.log(value)
}
}
Original answer:
You could do it like this: I removed the two-way-binding altogether, since we are using $event and value-attribute, so in this case ngModel is redundant. I also use change-event instead of click. So change your template to:
<md-checkbox *ngFor="let option of categoryFilters.options"
value="{{option.label}}" (change)="filterByCategory($event)">
{{option.label}}
</md-checkbox>
And in the component, let's see if the checkbox is checked before actually looking at the option value.
filterByCategory(event) {
if(event.checked) {
console.log(event.source.value)
}
}
This seems to work fine:
Demo

AngularJS Custom Directive using ng-options populated from service

I've really hit a brick wall with this, and I know I'm probably missing something here, but I'm stuck and need help. What I'm trying to do is use a service to populate the options in an ng-options directive; however, the ng-options are inside of a custom directive, and I've tried everything from track by, to testing it outside of the directive, inside the directive, etc. Can someone please take a look at this code and see if you can spot what I'm missing? Any help is greatly appreciated. It WILL work as far as executing the update to the ng-model; however, at page landing and record selection, it will not initially select the proper option, but if I take the track by out, it will initialize with the proper selection, it just won't update ng-model when/if I do that.
angular
.module('app')
.controller('mainCtrl', ['acctList', 'CONSTANTS', 'FORMFIELDS', function(acctList, CONSTANTS, FORMFIELDS) {
var mainCtrl = this;
mainCtrl.form = {};
mainCtrl.formFields = FORMFIELDS;
mainCtrl.currentRecord = null;
mainCtrl.editedRecord = {};
mainCtrl.setCurrentRecord = function(value) {
mainCtrl.currentRecord = value;
mainCtrl.editedRecord = angular.copy(mainCtrl.currentRecord);
};
mainCtrl.statuses = CONSTANTS.statuses;
}])
.value('FORMFIELDS', [
{
key: 'active_flag',
inputtype: 'select',
type: 'text',
class: 'form-control',
id: 'activeFl',
name: 'activeFl',
placeholder: 'Active Flag',
required: true,
maxlength: 1,
disabled: false,
labelfor: 'inputActiveFl',
labeltext: 'Active Flag',
field: 'mainCtrl.editedRecord.ACTIVE_FL',
options: 'list as list.desc for list in mainCtrl.statuses track by list.value'
}
])
.value('CONSTANTS',
{
statuses: [
{
id: 1,
value: "Y",
desc: "Active"
},
{
id: 2,
value: "N",
desc: "Inactive"
}
]
}
)
.directive('formTemplate', ['$compile', function($compile) {
function linker(scope, element, attr) {
scope.$watch(attr.modeltemp, function(modeltemp) {
// if ngModel already equals modeltemp or modeltemp doesn't exist, return
if (attr.ngModel == modeltemp || !modeltemp) return;
// remove all attributes to prevent duplication
element.removeAttr('placeholder');
element.removeAttr('type');
element.removeAttr('class');
element.removeAttr('id');
element.removeAttr('name');
element.removeAttr('ng-required');
element.removeAttr('maxlength');
element.removeAttr('ng-disabled');
// add the ng-model attribute presently tied to modeltemp
element.attr('ng-model', modeltemp);
// if modeltemp is blank, then remove ng-model, as it would be null
if (modeltemp == '') {
element.removeAttr('ng-model');
}
// Unbind all previous event handlers, this is
// necessary to remove previously linked models.
element.off();
// run a compile on the element, injecting scope, to reconstruct the element
$compile(element)(scope);
});
console.log(scope.acctCtrl);
}
// dynamic templating function associated with the templateUrl in the DDO
function template (tElement, tAttrs) {
// set the type variable equal to the value from the tAttr for 'inputtype' coming from the view
var type = tAttrs['inputtype'];
// just declaring the return variable for cleanliness
var tpl;
// begin the switch-case statement for each inputtype, then set it's return variable equal to the respective url
switch(type) {
case 'input':
tpl = '/common/directives/formTemplate/formTemplate.template.html';
break;
case 'select':
tpl = '/common/directives/formTemplate/formTemplateSelect.template.html';
break;
default:
tpl = '/common/directives/formTemplate/formTemplate.template.html';
break;
}
return tpl;
}
return {
restrict: 'EA',
replace: true,
templateUrl: template,
link: linker
};
}])
<form class="form-horizontal" ng-submit="submit()" name="mainCtrl.form.newAcctForm">
<div class="col-lg-6 form-fields" ng-repeat="fields in mainCtrl.formFields" ng-class="{ 'has-error': mainCtrl.form.newAcctForm.{{fields.name}}.$dirty }">
<label class="control-label" for="{{fields.labelfor}}">{{fields.labeltext}}</label>
<div form-template modeltemp="fields.field" inputtype="{{fields.inputtype}}"></div>
</div>
</form>
<select class="{{fields.class}}" id="{{fields.id}}" name="{{fields.name}}" ng-options="{{fields.options}}" ng-required="{{fields.required}}" maxlength="{{fields.maxlength}}" ng-disabled="{{fields.disabled}}">
<option value="">Please select...</option>
</select>
While this does work, did you consider using lifecycle hooks instead, waiting until after the view has loaded/initialized? Your solution works, but it's a bit like using a rocket launcher on an ant hill.

Angular change default value of select from filter

I have a select box which is populated with some data from my controller. When an input value changes the contents of the select box should be filtered and a default value should be assigned based on the is default property of the data object.
Is there any way this can be done using angular directives or would it need to be done as a custom filter function doing something along the lines of
angular.forEach(vm.data,function(item){
if (vm.q == item.someId && item.isDefault) {
vm.result = item.value;
}
});
My html looks something like
<div ng-app="myApp" ng-controller="ctrl as vm">
<input type="text" ng-model="vm.q">
<select ng-options="item.value as item.description for item in vm.data | filter:{someId:vm.q}" ng-model="vm.result"></select>
</div>
and my controller looks like:
(function(){
angular.module('myApp',[]);
angular
.module('myApp')
.controller('ctrl',ctrl);
function ctrl()
{
var vm = this;
vm.data = [
{
someId: '1',
description: 'test1',
value: 100,
isDefault: true
},
{
someId: '2',
description: 'test2',
value: 200,
isDefault: false
},
{
someId: '3',
description: 'test3',
value: 100,
isDefault: true
},
];
}
})();
See my plunkr demo here: http://plnkr.co/edit/RDhQWQcHFMQJvwOyHI4r?p=preview
Desired behaviour:
1) Enter 1 into text box
2) List should be filtered to 2 items
3) Select box should pre-select item 1 based on property isDefault set to true
Thanks in advance
I'd suggest you include some 3rd party library, like lodash, into your project to make working with arrays/collections that much easier.
After that you could add ng-change directive for your input.
<input type="text" ng-model="vm.q" ng-change="vm.onChange(vm.q)">
And the actual onChange function in the controller
vm.onChange = function(id) {
var item = _.findWhere(vm.data, { someId: id, isDefault: true });
vm.result = item ? item.value : null;
};
And there you have it.

Categories

Resources