I am trying to make a picklist dependent on another one
Controller picklist:Subtype
Dependent picklist
I succeded to do this
I put it in a lightning component
<ui:inputSelect aura:id="conType" label="Type" class="slds-select" change="{!c.onControllerFieldChange}" value="{!v.TypeV}">
<ui:inputSelect aura:id="conSubtype" label="Sub Type" value="{!v.SubTypeV}" disabled="{!v.isDependentDisable}" class="slds-select" />
I put this component from another lightning component
DependentSubtype is the child component
TypeV child component attribute to initialize the value of controller picklist (Type)
SubTypeV child component attribute to initialize the value of dependent picklist (SubType)
For the Controller picklist (Type) the initialization works
But for the dependent picklis (Subtype) it doesn't
Thanks in advance
It seems that your approach is right, however, its difficult to point out the problem from just that two lines of code. Here is a approach for dependent picklist,
// controller.js
({
doInit : function(component, event, helper) {
helper.loadOption1(component, event);
},
changeSecondPicklist : function(component, event, helper) {
helper.populateOption2(component, event);
}
})
// helper.js
({
loadOption1 : function(component, event) {
var option = [];
option.push('Type1.1');
option.push('Type1.2');
option.push('Type1.3');
component.set('v.option1', option);
},
populateOption2 : function(component, event) {
var value = event.getParam('value');
var option = [];
if (value == 'Type1.1') {
option.push('SubType1.1');
option.push('SubType1.2');
option.push('SubType1.3');
}
else if (value == 'Type1.2') {
option.push('SubType2.1');
option.push('SubType2.2');
option.push('SubType2.3');
}
else {
option.push('SubType3.1');
option.push('SubType3.2');
option.push('SubType3.3');
}
component.set('v.option2', option);
}
})
<!-- lightning component -->
<aura:component>
<aura:attribute name="option1" type="String[]" />
<aura:attribute name="option2" type="String[]" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<lightning:select name="select1" label="Type" required="true" onchange="{!c.changeSecondPicklist}">
<option value="">choose one...</option>
<aura:iteration items="{!v.option1}" var="item">
<option value="{!item}">{!item}</option>
</aura:iteration>
</lightning:select>
<lightning:select name="select2" label="SubType" required="true">
<option value="">choose one...</option>
<aura:iteration items="{!v.option2}" var="item">
<option value="{!item}">{!item}</option>
</aura:iteration>
</lightning:select>
</aura:component>
Here I have used lightning tag as Salesforce is going discontinue support for ui tags. The logic is onchange event of first picklist populates the options of dependent picklist.
Related
Hi I'm new to salesforce. I'm trying to develop a lightning component that will take user input, process that input & will display the value in two text box.My lightning component looks like
<aura:component implements="flexipage:availableForAllPageTypes,force:appHostable" access="global" controller="VisionController">
<!--Remember to define your binding attribute-->
<aura:attribute name="val" type="String"/>
<lightning:card title="Partner Information">
<div class="slds-p-around_medium">
<p>
<!--Set you attribute as the value of the lightning:input component-->
<lightning:input aura:name="val"
label ="Enter KPI"
value="{!v.val}"
type="text"
onchange="{!c.onChange}"/>
</p>
</div>
</lightning:card>
My JS controller looks like
({
onChange : function(component, event, helper) {
var action = component.get("c.getCallKPI")
action.setParams({
"value":val,
})
$A.enqueueAction(action)
}
})
I tried to do the iteration portion in controller using following code
var prediction=component.find("pred")
var predictionProb=component.find("predProb")
<aura:iteration items="{c.getCallKPI}" var="predUrl" >
prediction.value="{!predUrl.label}"
predictionProb.value="{!prediction.probability}"
</aura:iteration>
where prediction & predictionProb are id of two lightning inputs given in my component.But I'm getting syntax error at </aura:iteration>
If I'm doing it in component using following code
<aura:iteration items="{c.getCallKPI}" var="predUrl" >
<lightning:input id="pred" readonly="true" value="{!predUrl.label}"/>
<lightning:input id="predProb" readonly="true" value="{!predUrl.probability}" />
</aura:iteration>
Then it's not giving any error but not populating the inputs.
Can you guide how do I resolve this?
my getCallKPI is given below
#auraEnabled
public static List<KPI.Prediction> getCallKPI(string value) {
return KPI.Prediction;
}
You should use aura:iteration inside component markup.
In your component create new attribute of type "List".
<aura:attribute name="predictions" type="List"/>
In JS controller specify callback for action, in which set new attribute to response.getReturnValue().
action.setCallback(this, function(response) {
component.set("v.predictions", response.getReturnValue());
}
Calling a Server-Side Action
Inside component, iterate over returned records:
<aura:iteration items="{!v.predictions}" var="item">
//your logic
</aura:iteration>
aura:iteration
Here is my code in HTML.
<select class="form-control" (change)="onChange($event)"
[ngModel]="user" name="user" >
<option *ngFor="let user of users async as users;"
[ngValue]="user.userid">{{user.userName}} </option>
</select>
Here is my code in Component
onChange($event)
{
this.userid = $event.target.value;
console.log(this.userid);
}
When I log the value. Say the user has id - XYZ.
It's being logged as
1: (Index of the selection)
XYZ
How do I get only value without the index?
You don't need to pass the $event to the onChange() to get the selected option value.
The [ngModel] of the Select-tag will hold that instance for you.
I would rename the "user" model to selectedUser as that is more fitting.
Try it like this
<select class="form-control" (change)="onChange()"
[ngModel]="selectedUser" name="user" >
<option *ngFor="let user of users async as users;"
[ngValue]="user.userid">{{user.userName}} </option>
</select>
And in your component
export class YourComponent {
selectedUser: User;
onChange()
{
console.log(this.selectedUser);
}
//other stuff
}
For future readers, this is how I do it:
<select class="custom-select"
id="carType" formControlName="selectOptionCarType"
#carType
(change)="onSelectCarTypeValueChange(carType.value)">
....
</select>
And then:
onSelectCarTypeValueChange(value: string) {
this.carType=value.split(":", 2)[1].trim());
}
hi all i am using angularjs ng-repeat i have checkbox and dropdown in inside the repeat now my need is when check the checkbox value i want bind the dropdown but now when i check the checkbox all dropdown values are changed but my need i want bind the dropdown based checkbox help how to solve
ng-repeat code
<div ng-repeat="BFMaterialStream in BFMaterialStreams">
<input type="checkbox" ng-change="checkchange(BFMaterialStream.MaterialStream,$index)"
ng-model="selection.ids[BFMaterialStream.MaterialStream]" name="group" id="BFMaterialStream.MaterialStream" />
{{BFMaterialStream.MaterialStream}}
<select id="MaterialElevator" tabindex="7" required typeof="text" name="Elevator"
form="DistanceMatrixFormId" class="form-control"
ng-model="ViewGetBUMaterialStream.ToElevator"
>
<option value=''>Select</option>
<option ng-repeat="ViewGetBUMaterialStream in ViewGetBUMaterialStreams "
value="{{ViewGetBUMaterialStream.ToElevator}}"
>
{{ViewGetBUMaterialStream.ToElevator}}
</option>
</select>
</div>
check change time bind code
$scope.checkchange = function(Stream, index) {
$http.get('/ViewGetBUMaterialStream/' + Stream ).then(function (response) {
$scope.ViewGetBUMaterialStreams = response.data;
});
}
Make $scope.ViewGetBUMaterialStreams as an array.
In HTML change the repeat as
<option ng-repeat="ViewGetBUMaterialStream in ViewGetBUMaterialStreams[$index]"
value="{{ViewGetBUMaterialStream.ToElevator}}">
In change your $scope.ViewGetBUMaterialStreams = response.data assignment as $scope.ViewGetBUMaterialStreams[index] = response.data
JS looks like this:
$scope.ViewGetBUMaterialStreams = [];
$scope.checkchange = function(Stream, index) {
$http.get('/ViewGetBUMaterialStream/' + Stream ).then(function (response) {
$scope.ViewGetBUMaterialStreams[index] = response.data;
});
};
You may want to use ng-options directive:
<select ng-model="ViewGetBUMaterialStream.ToElevator"
ng-options="stream.ToElevator as stream for stream in ViewGetBUMaterialStreams">
<option value=''>Select</option>
</select>
Here is a JSFiddle of a simple use case of ng-options
I have implemented parsley on a complicated form that uses on-blur validation.
I have run into an issue where i go through the form, the fields are validated one by one, then based on a dropdown change, I have to destroy the Parlsey object in order to modify the validation and the fields that were valid are no longer valid.
How can I retain the already validated fields.
For example say I have the following:
<input type="text" id="1">
<input type="text" id="2">
<select id="select">
<option id=1>1</option>
<option id=2>2</option>
<option id=3>3</option>
</select>
<input type="text" id="3">
<input type="text" id="4">
<input type="text" id="5">
###Scenario:
I enter data in ID=1 and ID=2 textboxes, success class is added as I tab out of the textbox.
I change select box to option 2
I destroy parsley
Success class is removed from ID=1 and ID=2 textboxes
Currently I am doing the following:
$("#form").parsley().destroy();
$('#form').parsley({
successClass: "valid",
errorClass: "invalid",
errorsWrapper: '<div></div>',
errorTemplate: '<p></p>'
}).validate('section');
###What this does
This revalidates all the fields
###What I am looking for
I need ID=1 and ID=2 to remain valid after I destroy.
When you call destroy() all things from Parsley are destroyed. This means that all the classes, messages (DOM), objects and events will be destroyed.
If you're looking for a way to maintain the UI aspect, you can do that with a not-so-pretty solution:
In your styles, where you have .valid { ...} add another class: .valid, .fake-valid { ... }. Do the same for invalid.
Before calling destroy(), navigate through all the fields and check if there is a class valid or invalid
If so, apply a class called fake-valid or fake-invalid.
Using the event parsley:form:init, loop through the fields again and change their classes from fake-... to the correct classes.
Parsley will validate the fields but the UI is maintained.
Check this JsFiddle.
<style>
.valid, .fake-valid {
color: #468847;
background-color: #DFF0D8;
border: 1px solid #D6E9C6;
}
.invalid, .fake-invalid {
color: #B94A48;
background-color: #F2DEDE;
border: 1px solid #EED3D7;
}
</style>
<form id="myForm" method="post">
<input type="text" id="1" data-parsley-trigger="focusout" required />
<input type="text" id="2" data-parsley-trigger="focusout" required />
<select id="select">
<option id=1>1</option>
<option id=2>2</option>
<option id=3>3</option>
</select>
</form>
<script>
$(document).ready(function() {
var parsleyOpts = {
successClass: "valid",
errorClass: "invalid",
errorsWrapper: '<div></div>',
errorTemplate: '<p></p>'
};
var ParsleyForm = $("#myForm").parsley(parsleyOpts);
$("#select").on('change', function() {
// before destroy, add fake class
for (var i in ParsleyForm.fields) {
var elem = ParsleyForm.fields[i].$element;
if (elem.hasClass('valid'))
elem.addClass('fake-valid');
else if(elem.hasClass('invalid'))
elem.addClass('fake-invalid');
}
ParsleyForm.destroy();
ParsleyForm = $("#myForm").parsley(parsleyOpts);
});
// when parlsey is initialized, lets see if the fields have fake classes
// if so, add parsley classes
$.listen('parsley:form:init', function(formInstance) {
for (var i in formInstance.fields) {
var elem = formInstance.fields[i].$element;
if (elem.hasClass('fake-valid'))
elem.toggleClass('fake-valid valid')
if (elem.hasClass('fake-invalid'))
elem.toggleClass('fake-invalid invalid');
}
});
});
</script>
i'm trying to retrieve all ngModels within a transcluded directive. Is this the right way or is there a simpler solution to find the child model values?
Is there also a selector where i can use queries like this one ("input", "textarea", "select", ...)
The sample: http://plnkr.co/edit/tjjBEa1I1fIISvGbRz7e?p=preview
I don't know if this is the right approach. All your models are inside your $scope so why don't getting it from there directly?
For changes you shouldn't use jQuery like element.on('change', ...) style, instead bind an event listener to the model with $scope.$watch('model', ...) that would be the angular way.
Are you trying to disable all the inputs and clear their values when the 'Disable' checkbox is ticked?
I would recommend adding the ng-disabled directive to your inputs and binding it to a property on your model.
You can easily clear the input values by moving them onto an object on your model and then clearing that property when the controls are disabled.
Updated version of your plunkr: http://plnkr.co/edit/xKRF3rfAB8EcSKEBEeKd?p=preview
Here is the updated code based on your example:
app.js:
app.controller('MainCtrl', function($scope) {
// 1. Bind the 'Disable' checkbox's ng-model to this value.
$scope.disabled = false;
// 2. Move all your model data down one level onto the 'viewData' object.
// Now we can change all the input values just by changing the `$scope.viewData` object.
$scope.viewData = {
user: {
lastname: 'Doe',
firstname: 'John'
},
checker: true,
opt: 'Item 2'
};
// 3. Add a change callback on the 'Disable' checkbox to call this function.
// Replace the $scope.viewData to change the input values.
var originalData = null;
$scope.disabledChanged = function() {
if ($scope.disabled) {
// Clear the previous object.
originalData = $scope.viewData;
$scope.viewData = null;
} else {
// Revert back to the previous object.
$scope.viewData = originalData;
}
}
})
index.html:
<fieldset id="f">
<legend>
<label><input type="checkbox" child-disable child-disable-root="f" ng-model="disabled" ng-change="disabledChanged()" /> Disable</label>
</legend>
<hr />
<p><input type="checkbox" ng-model="viewData.checker" ng-disabled="disabled" /> Test</p>
<p><input type="text" ng-model="viewData.user.firstname" ng-disabled="disabled" />
<input type="text" ng-model="viewData.user.lastname" ng-disabled="disabled" /></p>
<p><textarea ng-model="viewData.multi" ng-disabled="disabled"></textarea></p>
<div>
<select ng-model="viewData.opt" ng-disabled="disabled">
<option>Item 1</option>
<option>Item 2</option>
<option>Item 3</option>
</select>
</div>
<div>
<button>Click</button>
</div>
</fieldset>