Решил посвятить выходные прекрасному, т.е. программированию,
делаю страницу-заготовку, состоящую из нескольких 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?
не работает, sectionsList пустой на фронте
[quote="Dmitry Lisovsky"]а не пробовал инитить лист в сеттере атрибута parentID?[/quote] не работает, sectionsList пустой на фронте