Validation rule to allow modification of limited fields only
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
I have a object that has more than 40 fields. There are 3 record types and each layout shows different fields.
Now, I want to write a validation rule which allows editing of limited fields only when the stage of record is progress.
For e.g.
If my School object have following fields:
School__c
Location__c
Name
Color__c
Class_c
Students__c
Teacher__c
Faculties__c
Department__c
stage__c
Now, If i have 3 record types called Type A, Type B, Type C.
In Type A, I want user be able to edit Color__c and Class__c fields.
In Type B, I want user to be able to edit Students__c and Teacher__c fields
In Type C, I want user to Edit Faculties__c, Department__c fields.
In all record type Name should be editable.
User should not be able to edit School__c, Location__c fields. The whole validation should run when stage__c = progress.
Can i write a validation rule that satisfies above condition.
formula validation validation-rule
add a comment |Â
up vote
1
down vote
favorite
I have a object that has more than 40 fields. There are 3 record types and each layout shows different fields.
Now, I want to write a validation rule which allows editing of limited fields only when the stage of record is progress.
For e.g.
If my School object have following fields:
School__c
Location__c
Name
Color__c
Class_c
Students__c
Teacher__c
Faculties__c
Department__c
stage__c
Now, If i have 3 record types called Type A, Type B, Type C.
In Type A, I want user be able to edit Color__c and Class__c fields.
In Type B, I want user to be able to edit Students__c and Teacher__c fields
In Type C, I want user to Edit Faculties__c, Department__c fields.
In all record type Name should be editable.
User should not be able to edit School__c, Location__c fields. The whole validation should run when stage__c = progress.
Can i write a validation rule that satisfies above condition.
formula validation validation-rule
This one we can achieve through validation rule. Is this condition for all the users correct ?
â Prem Anandh
Aug 9 at 16:20
1
While this can be done using validation rules, but considering you have 40 fields, your scenario is the opposite, i.e., you need to write a validation rule to block say 30 fields to be editable and only allow handful of fields to be editable when the stage reaches a particular value for a particular record type. This could get cumbersome to maintain. Recommend approach will be to implement this using a trigger.
â Jayant Das
Aug 9 at 16:34
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a object that has more than 40 fields. There are 3 record types and each layout shows different fields.
Now, I want to write a validation rule which allows editing of limited fields only when the stage of record is progress.
For e.g.
If my School object have following fields:
School__c
Location__c
Name
Color__c
Class_c
Students__c
Teacher__c
Faculties__c
Department__c
stage__c
Now, If i have 3 record types called Type A, Type B, Type C.
In Type A, I want user be able to edit Color__c and Class__c fields.
In Type B, I want user to be able to edit Students__c and Teacher__c fields
In Type C, I want user to Edit Faculties__c, Department__c fields.
In all record type Name should be editable.
User should not be able to edit School__c, Location__c fields. The whole validation should run when stage__c = progress.
Can i write a validation rule that satisfies above condition.
formula validation validation-rule
I have a object that has more than 40 fields. There are 3 record types and each layout shows different fields.
Now, I want to write a validation rule which allows editing of limited fields only when the stage of record is progress.
For e.g.
If my School object have following fields:
School__c
Location__c
Name
Color__c
Class_c
Students__c
Teacher__c
Faculties__c
Department__c
stage__c
Now, If i have 3 record types called Type A, Type B, Type C.
In Type A, I want user be able to edit Color__c and Class__c fields.
In Type B, I want user to be able to edit Students__c and Teacher__c fields
In Type C, I want user to Edit Faculties__c, Department__c fields.
In all record type Name should be editable.
User should not be able to edit School__c, Location__c fields. The whole validation should run when stage__c = progress.
Can i write a validation rule that satisfies above condition.
formula validation validation-rule
edited Aug 9 at 17:06
Mark Pond
17.7k13082
17.7k13082
asked Aug 9 at 16:06
lambad
1183
1183
This one we can achieve through validation rule. Is this condition for all the users correct ?
â Prem Anandh
Aug 9 at 16:20
1
While this can be done using validation rules, but considering you have 40 fields, your scenario is the opposite, i.e., you need to write a validation rule to block say 30 fields to be editable and only allow handful of fields to be editable when the stage reaches a particular value for a particular record type. This could get cumbersome to maintain. Recommend approach will be to implement this using a trigger.
â Jayant Das
Aug 9 at 16:34
add a comment |Â
This one we can achieve through validation rule. Is this condition for all the users correct ?
â Prem Anandh
Aug 9 at 16:20
1
While this can be done using validation rules, but considering you have 40 fields, your scenario is the opposite, i.e., you need to write a validation rule to block say 30 fields to be editable and only allow handful of fields to be editable when the stage reaches a particular value for a particular record type. This could get cumbersome to maintain. Recommend approach will be to implement this using a trigger.
â Jayant Das
Aug 9 at 16:34
This one we can achieve through validation rule. Is this condition for all the users correct ?
â Prem Anandh
Aug 9 at 16:20
This one we can achieve through validation rule. Is this condition for all the users correct ?
â Prem Anandh
Aug 9 at 16:20
1
1
While this can be done using validation rules, but considering you have 40 fields, your scenario is the opposite, i.e., you need to write a validation rule to block say 30 fields to be editable and only allow handful of fields to be editable when the stage reaches a particular value for a particular record type. This could get cumbersome to maintain. Recommend approach will be to implement this using a trigger.
â Jayant Das
Aug 9 at 16:34
While this can be done using validation rules, but considering you have 40 fields, your scenario is the opposite, i.e., you need to write a validation rule to block say 30 fields to be editable and only allow handful of fields to be editable when the stage reaches a particular value for a particular record type. This could get cumbersome to maintain. Recommend approach will be to implement this using a trigger.
â Jayant Das
Aug 9 at 16:34
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
4
down vote
You likely could write a validation rule to satisfy your conditions, but you might not be able to save that validation rule (because it'd likely go beyond the compiled character limit).
Validation rules aren't really meant to do what you're looking to do. Preventing certain fields from being edited is easy. The inverse of that, allowing certain fields to be edited, is hard.
A better declarative solution is to create new record types and page layouts, and mark the fields that you want to prevent from being edited as "read only" on those new layouts. You could use a workflow rule or process builder to automatically move your records into/out-of these special recordTypes.
Other than that, this would be a relatively simple trigger.
- Gather a list of all the field api names on your object
- Create a set of field api names you want to allow editing on (probably a
Map<String, Set<String>>
since you want different fields on different recordTypes) - Iterate over
trigger.new
, and check the record against its companion intrigger.old
- If a field is changed and not in your "allowed" set, add an error
some example code to get you going
Trigger myTrigger on MyObject(before update)
// We can gather the field API names through SObject describe information
List<String> fieldAPINames = new List<String>();
// This is one way to initialize a map
Map<String, Set<String>> editableFieldsByRecordType = new Map<String, Set<String>>
'RecType1' => new Set<String>'field1__c', 'field2__c', 'field3__c'
;
for(Schema.FieldDiscribeResult fdr :Schema.SObject.MyObject.fields.getMap().values())
// The getName() method of the FieldDescribeResult class gives you the API name of the field
fieldAPINames.add(fdr.getName());
for(MyObject newRec :Trigger.new)
MyObject oldRec = Trigger.oldMap.get(newRec.Id);
for(String currentField :fieldAPINames)
if(oldRec.get(currentField) != newRec.get(currentField) && !editableFieldsByRecordType.get(newRec.recordTypeName__c).contains(currentField))
newRec.addError('Field is not editable for this stage');
// After you find the first error, you may be able to move on to the next
// record.
// Comment the next line out if you want to catch _all_ attempted edits
break;
The big caveat here (besides me not testing for a particular stage) is that I assume you have a recordTypeName__c
field (a formula field) to pull the name of your recordType into the object you're working on.
Trigger context variables don't contain any "related data" (data on objects other than the one you're working on). If you need to use more than one period/dot/full-stop to access a field, like myRec.RecordType.Name
, that information is not available in trigger context variables.
To get that information, you either need to explicitly query for it, or have a formula field. There are other ways around that, but those are the easiest and most common approaches.
1
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
You likely could write a validation rule to satisfy your conditions, but you might not be able to save that validation rule (because it'd likely go beyond the compiled character limit).
Validation rules aren't really meant to do what you're looking to do. Preventing certain fields from being edited is easy. The inverse of that, allowing certain fields to be edited, is hard.
A better declarative solution is to create new record types and page layouts, and mark the fields that you want to prevent from being edited as "read only" on those new layouts. You could use a workflow rule or process builder to automatically move your records into/out-of these special recordTypes.
Other than that, this would be a relatively simple trigger.
- Gather a list of all the field api names on your object
- Create a set of field api names you want to allow editing on (probably a
Map<String, Set<String>>
since you want different fields on different recordTypes) - Iterate over
trigger.new
, and check the record against its companion intrigger.old
- If a field is changed and not in your "allowed" set, add an error
some example code to get you going
Trigger myTrigger on MyObject(before update)
// We can gather the field API names through SObject describe information
List<String> fieldAPINames = new List<String>();
// This is one way to initialize a map
Map<String, Set<String>> editableFieldsByRecordType = new Map<String, Set<String>>
'RecType1' => new Set<String>'field1__c', 'field2__c', 'field3__c'
;
for(Schema.FieldDiscribeResult fdr :Schema.SObject.MyObject.fields.getMap().values())
// The getName() method of the FieldDescribeResult class gives you the API name of the field
fieldAPINames.add(fdr.getName());
for(MyObject newRec :Trigger.new)
MyObject oldRec = Trigger.oldMap.get(newRec.Id);
for(String currentField :fieldAPINames)
if(oldRec.get(currentField) != newRec.get(currentField) && !editableFieldsByRecordType.get(newRec.recordTypeName__c).contains(currentField))
newRec.addError('Field is not editable for this stage');
// After you find the first error, you may be able to move on to the next
// record.
// Comment the next line out if you want to catch _all_ attempted edits
break;
The big caveat here (besides me not testing for a particular stage) is that I assume you have a recordTypeName__c
field (a formula field) to pull the name of your recordType into the object you're working on.
Trigger context variables don't contain any "related data" (data on objects other than the one you're working on). If you need to use more than one period/dot/full-stop to access a field, like myRec.RecordType.Name
, that information is not available in trigger context variables.
To get that information, you either need to explicitly query for it, or have a formula field. There are other ways around that, but those are the easiest and most common approaches.
1
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
add a comment |Â
up vote
4
down vote
You likely could write a validation rule to satisfy your conditions, but you might not be able to save that validation rule (because it'd likely go beyond the compiled character limit).
Validation rules aren't really meant to do what you're looking to do. Preventing certain fields from being edited is easy. The inverse of that, allowing certain fields to be edited, is hard.
A better declarative solution is to create new record types and page layouts, and mark the fields that you want to prevent from being edited as "read only" on those new layouts. You could use a workflow rule or process builder to automatically move your records into/out-of these special recordTypes.
Other than that, this would be a relatively simple trigger.
- Gather a list of all the field api names on your object
- Create a set of field api names you want to allow editing on (probably a
Map<String, Set<String>>
since you want different fields on different recordTypes) - Iterate over
trigger.new
, and check the record against its companion intrigger.old
- If a field is changed and not in your "allowed" set, add an error
some example code to get you going
Trigger myTrigger on MyObject(before update)
// We can gather the field API names through SObject describe information
List<String> fieldAPINames = new List<String>();
// This is one way to initialize a map
Map<String, Set<String>> editableFieldsByRecordType = new Map<String, Set<String>>
'RecType1' => new Set<String>'field1__c', 'field2__c', 'field3__c'
;
for(Schema.FieldDiscribeResult fdr :Schema.SObject.MyObject.fields.getMap().values())
// The getName() method of the FieldDescribeResult class gives you the API name of the field
fieldAPINames.add(fdr.getName());
for(MyObject newRec :Trigger.new)
MyObject oldRec = Trigger.oldMap.get(newRec.Id);
for(String currentField :fieldAPINames)
if(oldRec.get(currentField) != newRec.get(currentField) && !editableFieldsByRecordType.get(newRec.recordTypeName__c).contains(currentField))
newRec.addError('Field is not editable for this stage');
// After you find the first error, you may be able to move on to the next
// record.
// Comment the next line out if you want to catch _all_ attempted edits
break;
The big caveat here (besides me not testing for a particular stage) is that I assume you have a recordTypeName__c
field (a formula field) to pull the name of your recordType into the object you're working on.
Trigger context variables don't contain any "related data" (data on objects other than the one you're working on). If you need to use more than one period/dot/full-stop to access a field, like myRec.RecordType.Name
, that information is not available in trigger context variables.
To get that information, you either need to explicitly query for it, or have a formula field. There are other ways around that, but those are the easiest and most common approaches.
1
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
add a comment |Â
up vote
4
down vote
up vote
4
down vote
You likely could write a validation rule to satisfy your conditions, but you might not be able to save that validation rule (because it'd likely go beyond the compiled character limit).
Validation rules aren't really meant to do what you're looking to do. Preventing certain fields from being edited is easy. The inverse of that, allowing certain fields to be edited, is hard.
A better declarative solution is to create new record types and page layouts, and mark the fields that you want to prevent from being edited as "read only" on those new layouts. You could use a workflow rule or process builder to automatically move your records into/out-of these special recordTypes.
Other than that, this would be a relatively simple trigger.
- Gather a list of all the field api names on your object
- Create a set of field api names you want to allow editing on (probably a
Map<String, Set<String>>
since you want different fields on different recordTypes) - Iterate over
trigger.new
, and check the record against its companion intrigger.old
- If a field is changed and not in your "allowed" set, add an error
some example code to get you going
Trigger myTrigger on MyObject(before update)
// We can gather the field API names through SObject describe information
List<String> fieldAPINames = new List<String>();
// This is one way to initialize a map
Map<String, Set<String>> editableFieldsByRecordType = new Map<String, Set<String>>
'RecType1' => new Set<String>'field1__c', 'field2__c', 'field3__c'
;
for(Schema.FieldDiscribeResult fdr :Schema.SObject.MyObject.fields.getMap().values())
// The getName() method of the FieldDescribeResult class gives you the API name of the field
fieldAPINames.add(fdr.getName());
for(MyObject newRec :Trigger.new)
MyObject oldRec = Trigger.oldMap.get(newRec.Id);
for(String currentField :fieldAPINames)
if(oldRec.get(currentField) != newRec.get(currentField) && !editableFieldsByRecordType.get(newRec.recordTypeName__c).contains(currentField))
newRec.addError('Field is not editable for this stage');
// After you find the first error, you may be able to move on to the next
// record.
// Comment the next line out if you want to catch _all_ attempted edits
break;
The big caveat here (besides me not testing for a particular stage) is that I assume you have a recordTypeName__c
field (a formula field) to pull the name of your recordType into the object you're working on.
Trigger context variables don't contain any "related data" (data on objects other than the one you're working on). If you need to use more than one period/dot/full-stop to access a field, like myRec.RecordType.Name
, that information is not available in trigger context variables.
To get that information, you either need to explicitly query for it, or have a formula field. There are other ways around that, but those are the easiest and most common approaches.
You likely could write a validation rule to satisfy your conditions, but you might not be able to save that validation rule (because it'd likely go beyond the compiled character limit).
Validation rules aren't really meant to do what you're looking to do. Preventing certain fields from being edited is easy. The inverse of that, allowing certain fields to be edited, is hard.
A better declarative solution is to create new record types and page layouts, and mark the fields that you want to prevent from being edited as "read only" on those new layouts. You could use a workflow rule or process builder to automatically move your records into/out-of these special recordTypes.
Other than that, this would be a relatively simple trigger.
- Gather a list of all the field api names on your object
- Create a set of field api names you want to allow editing on (probably a
Map<String, Set<String>>
since you want different fields on different recordTypes) - Iterate over
trigger.new
, and check the record against its companion intrigger.old
- If a field is changed and not in your "allowed" set, add an error
some example code to get you going
Trigger myTrigger on MyObject(before update)
// We can gather the field API names through SObject describe information
List<String> fieldAPINames = new List<String>();
// This is one way to initialize a map
Map<String, Set<String>> editableFieldsByRecordType = new Map<String, Set<String>>
'RecType1' => new Set<String>'field1__c', 'field2__c', 'field3__c'
;
for(Schema.FieldDiscribeResult fdr :Schema.SObject.MyObject.fields.getMap().values())
// The getName() method of the FieldDescribeResult class gives you the API name of the field
fieldAPINames.add(fdr.getName());
for(MyObject newRec :Trigger.new)
MyObject oldRec = Trigger.oldMap.get(newRec.Id);
for(String currentField :fieldAPINames)
if(oldRec.get(currentField) != newRec.get(currentField) && !editableFieldsByRecordType.get(newRec.recordTypeName__c).contains(currentField))
newRec.addError('Field is not editable for this stage');
// After you find the first error, you may be able to move on to the next
// record.
// Comment the next line out if you want to catch _all_ attempted edits
break;
The big caveat here (besides me not testing for a particular stage) is that I assume you have a recordTypeName__c
field (a formula field) to pull the name of your recordType into the object you're working on.
Trigger context variables don't contain any "related data" (data on objects other than the one you're working on). If you need to use more than one period/dot/full-stop to access a field, like myRec.RecordType.Name
, that information is not available in trigger context variables.
To get that information, you either need to explicitly query for it, or have a formula field. There are other ways around that, but those are the easiest and most common approaches.
answered Aug 9 at 16:43
Derek F
17.1k21344
17.1k21344
1
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
add a comment |Â
1
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
1
1
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
A fieldset (or more likely a couple fieldsets) can be leveraged so that the list of fields is controlled by something that can be edited in Setup rather than hardcoded.
â Mark Pond
Aug 9 at 17:09
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f228362%2fvalidation-rule-to-allow-modification-of-limited-fields-only%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
This one we can achieve through validation rule. Is this condition for all the users correct ?
â Prem Anandh
Aug 9 at 16:20
1
While this can be done using validation rules, but considering you have 40 fields, your scenario is the opposite, i.e., you need to write a validation rule to block say 30 fields to be editable and only allow handful of fields to be editable when the stage reaches a particular value for a particular record type. This could get cumbersome to maintain. Recommend approach will be to implement this using a trigger.
â Jayant Das
Aug 9 at 16:34