Регистрация  |  Вход

Проблема с VF компонентом

Решил посвятить выходные прекрасному, т.е. программированию,

делаю страницу-заготовку, состоящую из нескольких VF компонентов, связанных друг с другом actionFunction

и все работает, кроме одного (и при этом совершенно простого): не могу заставить Компонентный контроллер сохранить измененные записи,
вначале пришлось узнать про allowDML="true"

затем я понял, что апдейт записей происходит, но дело в том, что переменная, хранящая записи, осталась неизменной, т.е. там нет изменений сдаланных пользователем на фронте. и я не знаю почему... не вижу, где - что я упускаю

вот контроллер:

public with sharing class  ContentSection_Comp_Contrl{

Public ID parentID {set; get;}
Public List<Section__c> sectionsList {set; get{return [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];}}


public void saveAnswers(){

Public List<Question__c> questions = new List<Question__c>();

for(Section__c s :sectionsList) questions.addAll(s.Questions__r);

update questions; //поле Yes_or_No__c осталось неизмененным!!!

}
}

вот компонент:

<apex:component controller="ContentSection_Comp_Contrl"  allowDML="true" >
<apex:attribute name="parent_ID" assignTo="{!parentID}" description="Id of the parent record (Chapter__c) " required="true" type="ID"/>

<apex:repeat value="{!sectionsList}" var="section">

<h2>{!section.name}</h2>
<ul>
<apex:repeat value="{!section.Questions__r}" var="question">
<li>{!question.name}: <apex:inputField value="{!question.Yes_or_No__c}"/></li> ВОТ ЗДЕСЬ ЮЗЕР МЕНЯЕТ ЗНАЧЕНИЕ ПОЛЯ
</apex:repeat>
</ul>

</apex:repeat>

<apex:commandButton action="{!saveAnswers}" value="SAVE" status="actStatusId"/>

</apex:component>

почему sectionsList не вернулась в контроллер с фронта с пользовательским вводом?

Решил посвятить выходные прекрасному, т.е. программированию,

делаю страницу-заготовку, состоящую из нескольких VF компонентов, связанных друг с другом actionFunction

и все работает, кроме одного (и при этом совершенно простого): не могу заставить Компонентный контроллер сохранить измененные записи,
вначале пришлось узнать про  allowDML="true"

затем я понял, что апдейт записей происходит, но дело в том, что переменная, хранящая записи, осталась неизменной, т.е. там нет изменений сдаланных пользователем на фронте. и я не знаю почему... не вижу, где - что я упускаю

вот контроллер:
[code]
public with sharing class  ContentSection_Comp_Contrl{

Public ID parentID  {set; get;}
Public List<Section__c> [b]sectionsList[/b]  {set; get{return [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];}}


public void saveAnswers(){

Public List<Question__c> questions = new List<Question__c>();
    
for(Section__c s :[b]sectionsList[/b]) questions.addAll(s.Questions__r);
    
    update questions; //поле Yes_or_No__c осталось неизмененным!!!
   
} 
}

[/code]

вот компонент:

[code]
<apex:component controller="ContentSection_Comp_Contrl"  allowDML="true" >
<apex:attribute name="parent_ID" assignTo="{!parentID}" description="Id of the parent record (Chapter__c) " required="true" type="ID"/>

<apex:repeat value="{![b]sectionsList[/b]}" var="section">

<h2>{!section.name}</h2>
<ul>
<apex:repeat value="{!section.Questions__r}" var="question">
<li>{!question.name}: [b]<apex:inputField value="{!question.Yes_or_No__c}"/>[/b]</li> ВОТ ЗДЕСЬ ЮЗЕР МЕНЯЕТ ЗНАЧЕНИЕ ПОЛЯ
</apex:repeat>
</ul>
    
</apex:repeat>

    <apex:commandButton action="{!saveAnswers}" value="SAVE" status="actStatusId"/>
    
</apex:component>
[/code]

почему [b]sectionsList[/b] не вернулась в контроллер с фронта с пользовательским вводом?

У тебя геттер постонно ретривит из бд. Делай инит листа отдельным методом, а геттер не трогай :)

У тебя геттер постонно ретривит из бд. Делай инит листа отдельным методом, а геттер не трогай :)

Спасибо, Дмитрий, за наводку.

получается, что каждый раз, когда компонент обращается к своему контроллеру, sectionsList просто перезаписывается заново? а если в гетер делать проверку вроде if(sectionsList == null)?

какое твое решение?

я обычно заполняю все переменные в конструкторе контроллера, но здесь у меня так не получилось: требуется parentID, который приход в компонент как атрибут, и у меня такое ощущение, что он нулевой в конструкторе, так как ничего не кверится, если попробовать заполнить sectionsList в конструкторе... я не стал разбираться, просто вынес все в гетер, а там как видно свои нюансы :)

Спасибо, Дмитрий, за наводку.

получается, что каждый раз, когда компонент обращается к своему контроллеру, [b]sectionsList[/b] просто перезаписывается заново? а если в гетер делать проверку вроде if([b]sectionsList[/b] == null)?

какое твое решение?

я обычно заполняю все переменные в конструкторе контроллера, но здесь у меня так не получилось: требуется parentID, который приход в компонент как атрибут, и у меня такое ощущение, что [b]он нулевой в конструкторе[/b], так как ничего не кверится, если попробовать заполнить [b]sectionsList[/b] в конструкторе... я не стал разбираться, просто вынес все в гетер, а там как видно свои нюансы :)

Проблема в том что setter атрибутов вызывается после конструктора, поэтому в кострукторе у тебя пустой parentID. Пробуй инитить лист в сеттере аюатрибута parentID.

Решение с проверкой листа на null тоже должно сработать.

Проблема в том что setter атрибутов вызывается после конструктора, поэтому в кострукторе у тебя пустой parentID. Пробуй инитить лист в сеттере аюатрибута parentID.

Решение с проверкой листа на null тоже должно сработать.

Ну да, как бы у тебя при каждом обращении к переменной будет отрабатывать SOQL. попробуй 10 раз написать строчку с обращением к переменной.
Да, для этого и ставят проверку на null чтобы достать из базы 1 раз, а потом возвращать то что находится в переменной.
Лучше разберись глубже с геттерами и сеттерами. Это тема выходит за рамки компонентов и является более важной.

Ну да, как бы у тебя при каждом обращении к переменной будет отрабатывать SOQL. попробуй 10 раз написать строчку с обращением к переменной.
Да, для этого и ставят проверку на null чтобы достать из базы 1 раз, а потом возвращать то что находится в переменной. 
Лучше разберись глубже с геттерами и сеттерами. Это тема выходит за рамки компонентов и является более важной. 

спасибо, разобрался, но удивительное дела - все равно не работает

вот свойство:

Public List<Section__c> sectionsList  {get {


if(sectionsList == null) {

sectionsList = [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];

}
return sectionsList;

}

set;
}

так вот, код не заходит в ветку if(sectionsList == null)
он не заходит даже так if(sectionsList != null)

и падает на нуле вот так if(sectionsList.isEmpty()) or if(sectionsList.size()>0)

не понятно...

спасибо, разобрался, но удивительное дела - все равно не работает

вот свойство:

[code]Public List<Section__c> sectionsList  {get {
    
    
   if(sectionsList == null)  {
        
        sectionsList = [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];

    }
    return sectionsList;
    
    }
                                      
   set; 
   }[/code]

так вот, код не заходит в ветку [b]if(sectionsList == null)[/b] 
он не заходит даже так if(sectionsList != null)

и падает на нуле вот так  if(sectionsList.isEmpty()) or   if(sectionsList.size()>0)

не понятно...

Да что ж у тебя все не слава богу ?
100 лет используют этот прием на автопилоте и у всех все работает.
Завтра как буду у компа проверь твой копипаст.

Кстати, как у тебя получается сломать верстку для code?
Ты откуда копируешь свои исходники? Откуда у тебя внутри кода все через html теги отформатировано???

Да что ж у тебя все не слава богу :D ? 
100 лет используют этот прием на автопилоте и у всех все работает. 
Завтра как буду у компа проверь твой копипаст.

Кстати, как у тебя получается сломать верстку для code?
Ты откуда копируешь свои исходники? Откуда у тебя внутри кода все через html теги отформатировано???

вот так работает:

Public List<Section__c> sectionsList  {set; get;}

public String label {get{
initData();
label='';
return label;
}set;}

Public void initData(){

sectionsList = [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];

}

то есть пришлось выдумывать свойство label (и обращаться к нему на фронте), и тогда все работает и сохранется.

но я так и не понял, почему вот так переменная sectionsList перезаписывается геттером при обращении с фронта к методу контроллера:

Public List<Section__c> sectionsList  {set; get{return [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];}}

а в примере выше она не перезаписывается... ведь ситуация схожая

вот так работает:

[code]Public List<Section__c> sectionsList  {set; get;}

public String label {get{
            initData();
            label='';
        return label;
    }set;}
 

Public void initData(){

        sectionsList = [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];

}[/code]

то есть пришлось выдумывать свойство label (и обращаться к нему на фронте), и тогда все работает и сохранется.

но я так и не понял, почему вот так переменная sectionsList перезаписывается геттером при обращении с фронта к методу контроллера:
[code]
Public List<Section__c> sectionsList  {set; get{return [SELECT ID, name, (SELECT ID, Name, Yes_or_No__c FROM Questions__r) FROM Section__c WHERE Chapter__c = :parentID ORDER BY CreatedDate];}}[/code]

а в примере выше она не перезаписывается... ведь ситуация схожая

 

а не пробовал инитить лист в сеттере атрибута parentID?

а не пробовал инитить лист в сеттере атрибута parentID?

Dmitry Lisovsky
а не пробовал инитить лист в сеттере атрибута parentID?

не работает, sectionsList пустой на фронте

[quote="Dmitry Lisovsky"]а не пробовал инитить лист в сеттере атрибута parentID?[/quote]
не работает, sectionsList пустой на фронте