Hey again,
apparently my function still missed something: it couldn’t handle posts where the first or the last field in the repeater (a step) had an empty sub-field (step title). I figured it out somehow (please see below) but now I have a different problem which I cannot find a solution for – I don’t want the whole loop to happen if all sub-fields are empty. the thing is, it’s impossible to get all sub-fields outside the loop in order to count the empty ones before the loop has started.
This is what I have now:
//table of content for instructuble posts
function itamar_index_for_instructubles() {
// check if the instructuble has steps
if( have_rows('שלבים') ):
$i=0; //counts all iterations, inside the loop
$x=0; //counts only iterations with a step title, inside the loop
$rows = get_field('שלבים');
$total=count($rows); //counts the total number of iterations outside the loop to determine the last one
// loop through the steps
while ( have_rows('שלבים') ) : the_row();
$step_title = get_sub_field('שם_השלב');
$i++;
// first iteration
if($i == 1) :
//open tags for the table of content
$indexed = '<div class="info-table" id="index"><div class="title">תוכן עניינים<span id="oc-index">-</span></div><div class="body"><ul class="indexed-content">';
endif;
if($step_title!='' && $i >= 1) :
$x++;
$indexed .= '<li>'.$x.'. <a href="#anc'.$x.'">'.$step_title.'</a></li>' ;
endif;
// last iteration
if($i == $total) :
//closing tags for the table of content
$indexed .= '</ul></div><div class="bottom"></div></div>';
endif;
endwhile;
echo $indexed;
endif;
}
And what I would like to do is something like:
/**** before the loop has started ****/
$total=0;
$sub_fields = //a function to get all subfields under a given repeater
foreach($sub_fields as $sub_field){
if ($sub_field->content != ""){
$total++;
}
}
/*****/
/**** inside the loop ****/
// first iteration
if($total != 0 && $i == 1) :
//open tags for the table of content
$indexed = '<div class="info-table" id="index"><div class="title">תוכן עניינים<span id="oc-index">-</span></div><div class="body"><ul class="indexed-content">';
endif;
/*****/
Is there a way to get that done?
Thanks a lot,
Itamar
EDIT:
I found the way:
//table of content for instructuble posts
function itamar_index_for_instructubles() {
// check if the instructuble has steps
if( have_rows('שלבים') ):
$rows = get_field('שלבים');
$total_steps = count($rows); //counts the total number of steps outside the loop to determine the last one, outside the loop
$total_titles = 0; //counts the total number of non-empty step titels, outside the loop
if($rows){
foreach($rows as $row){
if($row['שם_השלב'] != ""){$total_titles++;}
}
}
// loop through the steps
if($total_titles != 0) :
$i=0; //counts all iterations, inside the loop
$x=0; //counts only iterations with a step title, inside the loop
while ( have_rows('שלבים') ) : the_row();
$step_title = get_sub_field('שם_השלב');
$i++;
// first iteration
if($i == 1) :
//open tags for the table of content
$indexed .= '<div class="info-table" id="index"><div class="title">תוכן עניינים<span id="oc-index">-</span></div><div class="body"><ul class="indexed-content">';
endif;
if($step_title!='' && $i >= 1) :
$x++;
$indexed .= '<li>'.$x.'. <a href="#anc'.$x.'">'.$step_title.'</a></li>' ;
endif;
// last iteration
if($i == $total_steps) :
//closing tags for the table of content
$indexed .= '</ul></div><div class="bottom"></div></div>';
endif;
endwhile;
endif;
echo $indexed;
endif;
}
Hey James and thanks for the reply,
It seems like there is a problem with $step_num=count($rows);
, it returns 1
and therefore the if($i == $step_num)
statement occurs on the first iteration and not the last.
Is there a better way to count the repeater rows?
EDIT: Solution!
It’s impossible to count have_rows()
, the right way is counting the get_field()
itself. so easy 🙂
function itamar_index_for_instructubles() {
// check if the instructuble has steps
if( have_rows('שלבים') ):
$i=0;
$rows = get_field('שלבים');
$step_num=count($rows);
// loop through the steps
while ( have_rows('שלבים') ) : the_row();
$i++;
$step_title = get_sub_field('שם_השלב');
if($step_title!='') :
// first iteration
if($i == 1) :
//open tags for the table of content
$indexed = '<div class="info-table" id="index"><div class="title">תוכן עניינים<span id="oc-index">-</span></div><div class="body"><ul class="indexed-content">';
endif;
$indexed .= '<li>'.$i.'. <a href="#anc'.$i.'">'.$step_title.'</a></li>' ;
// last iteration
if($i == $step_num-1) :
//closing tags for the table of content
$indexed .= '</ul></div><div class="bottom"></div></div>';
endif;
endif;
endwhile;
echo $indexed;
endif;
}
Thanks!
Itamar
although this is old, for those who look for a good solution for this issue of validating the first row’s fields in a repeater, here is what I just figured out:
//validate first step
add_filter('acf/validate_value/key=field_57bc841e7f973', 'itamar_acf_validate_value__fs', 10, 4);
function itamar_acf_validate_value__fs( $valid, $value, $field, $input ){
// bail early if value is already invalid
if( !$valid ) {
return $valid;
}
// load data
$repeater_field = $_POST['acf']['field_57bc841e7f973']; //repater parent key
reset($repeater_field); //reset repeater array to the rist row
$first_field = key($repeater_field); //get first key in the repeater array
$my_text_field = $_POST['acf']['field_57bc841e7f973'][$first_field]['field_57bc8a5447d06']; //specific field
$characters = mb_strlen($my_text_field, 'utf-8');
if ( $characters < 100 ) {
$valid = 'כתבת '.$characters.' תווים בלבד בתוכן השלב הראשון. עליך לכתוב לפחות 100 תווים.';
}
// return
return $valid;
}
in this case the validation is for a specific field under the first row in a specific repeater. you can change the characters count to 1 and then you get a real “required” field.
for those who have the same problem. thanks to James, here is the full solution:
(function($) {
$(document).ready(function(){
$("#tagsdiv-knowlendge").appendTo(".acf-field-57bc8db4167d8");
$("#tagsdiv-tools").appendTo(".acf-field-57bc8dcc167d9");
$("#tagsdiv-materials").appendTo(".acf-field-57bc8de1167da");
$("#aboutcontent").append("<div class='clear' style='height:8px;'></div>");
if( $("#in-category-1").is(':checked') ){
$('.acf-field-57bc88444d651 .acf-input').append( $('#postdivrich') );
}
else{
$("#acf-group_57bc87aa02bb7").addClass("acf-hidden");
}
$('#in-category-1').on("change", function(){
if( $(this).is(':checked') ){
$('.acf-field-57bc88444d651 .acf-input').append( $('#postdivrich') );
tinymce.EditorManager.execCommand('mceRemoveEditor',true, "content");
tinymce.EditorManager.execCommand('mceAddEditor',true, "content");
} else {
$('#post-body-content').append( $('#postdivrich') );
tinymce.EditorManager.execCommand('mceRemoveEditor',true, "content");
tinymce.EditorManager.execCommand('mceAddEditor',true, "content");
$("#acf-group_57bc87aa02bb7").addClass("acf-hidden");
}
});
});
})(jQuery);
Actually now I see that the soution doesn’t reallt work for me. I’m trying to apply this validation on a wysiwyg field and the strlen
always returns 0 characters.
Itamar
Hey,
I’ve now tried this solution and it work’s! thanks! even though, I have two things I’m trying to achieve with no success:
1. Is it possible to do this validation to the first field in a repeater? only to the first.
2. Is it possible to apply this validation on the wp core editor?
Thanks,
Itamar
^^
here is a video explaining the problem.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.