Сохранение и обновление контакта через inputfield

Сохранение и обновление контакта через inputfield

Есть контроллер и страница. На данный момент при вводе email подтягиваются Last и First name. Но есть необходимость сохранить новый контакт или обновить старый через input. На данный момент пытаюсь сохранить через
хотя бы кнопку, но утыкаюсь Attempt to de-reference a null object. Почему нулевой объект, не понятно.

global class ProductListController {

// List of products wich are exist in the Warehouse (product table)
public List <Product_Table__c> existProduct { get{return [SELECT Id, Image_Url__c, Name, Product_Description__c, Unit_Price__c
FROM Product_Table__c ];} set; }

public String contactDefaultQuery = 'SELECT Id,FirstName, LastName, Email FROM Contact LIMIT 100';
//String Search
public String searchContactEmail {get; set;}
public static Contact contact { get; set; }
List <Contact> conlist { get; set; }
public String firstname { get; set; }
public String lastname { get; set; }
public String email { get; set; }

// Id selected product click "Buy"
public Id selectedProductId { get; set; }
public Product_Table__c prod { get; set; }
// List selected product
public List<Product_Table__c> currentProductsDatail { get; set; }
public List<Product_Table__c> currentProductsOrder { get; set; }

// Constructor
public ProductListController (){
contact = [SELECT Id,Email, FirstName, LastName
FROM Contact
WHERE Email =:searchContactEmail];
conlist = new List <Contact>();
contact = new Contact();
searchContactEmail = '';
currentProductsDatail = new List<Product_Table__c>();
}

// Get new page "ProductDetails" and details selected product
public pageReference getPage(){

currentProductsDatail = [SELECT Id, Image_Url__c, Name, Product_Description__c, Unit_Price__c, Unit_Available__c
FROM Product_Table__c WHERE Id =: selectedProductId ];

pageReference ref = new pageReference('/apex/ProductDetails');
return ref;

}

public pageReference getPurcharePage (){
prod = [SELECT Id, Name, Unit_Price__c
FROM Product_Table__c WHERE Id =: selectedProductId ];

pageReference ref = new pageReference('/apex/PurchareProduct');

return ref;
}


public pageReference getProductListPage (){

pageReference ref = new pageReference('/apex/Product_List');
return ref;
}


@RemoteAction
global static Contact getContact(String searchContactEmail) {

contact = [SELECT Id, FirstName, LastName
FROM Contact
WHERE Email =:searchContactEmail];
return contact;

}



public pageReference save (){
contact con = new contact (FirstName = firstname, LastName = lastname, Email = email);
conlist.add(con);
insert con;
return null;
}

}

<apex:page controller="ProductListController"  >

<apex:slds />
<apex:form >


<script type="text/javascript">
function getRemoteContact() {

var searchContactEmail = document.getElementById('contactsearch').value;

Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.ProductListController.getContact}',
searchContactEmail,
function(result, event){
if(event.status){

document.getElementById('remoteConFname').value = result.FirstName;

document.getElementById('remoteConLname').value = result.LastName;



} else if (event.type == 'exception'){
document.getElementById(
"responseErrors"
).innerHTML = event.message = "<br/>\n<pre>" + event.where + "</pre>";
}else{
document.getElementById(
"responseErrors"
).innerHTML = event.message;
}
},
{escape:true}

);
}

</script>


<div class="slds-grid slds-wrap slds-box slds-theme_shade ">
<div class="slds-text-align_center slds-text-title_caps slds-size_1-of-2">
<span class= "slds-page-header__title slds truncate">Contact information</span>
</div>
<div class="slds-text-align_center slds-text-title_caps slds-size_1-of-2">
<span class= "slds-page-header__title slds truncate">Product information</span>

</div>
</div>

<div class="slds-grid" >
<div class="slds-text-align_center slds-size_1-of-2" >




<br/>
<label class = "slds-text-heading_small" for="Email" style = "padding-left:52px" >Email</label>
<input id = "contactsearch" class = "slds-input" name="Email" style = "width: 30%;" onchange="getRemoteContact(this.value)" value = "{!contact.email}" />


<br/><br/>
<label class = "slds-text-heading_small" for="FirstName" style = "padding-left:12px" >First Name</label>
<input class = "slds-input" name="FirstName" style = "width: 30%;" type="text" id ="remoteConFname" placeholder="" value="{!contact.firstname}" />
<br/><br/>
<label class = "slds-text-heading_small" for="LastName" >Last Name <abbr class="slds-required" title="required">* </abbr> </label>
<input class = "slds-input" name="LastName" style = "width: 30%;" type="text" id ="remoteConLname" placeholder="" value="{!contact.lastname}" />
<br/><br/>
</div>

<div class="slds-text-align_center slds-size_1-of-2">
<br/>
<p class = "slds-text-heading_small" style = "padding-right:200px">Product Name &nbsp; {!prod.Name}</p>
<br/>
<p class = "slds-text-heading_small" style = "padding-right:125px">Cost &nbsp; {!prod.Unit_Price__c}$ </p>
<br/>
<label class = "slds-text-heading_small" for="UnitCount" >Unit Count</label>
<input class = "slds-input" id="UnitCount" name="UnitCount" style = "width: 30%;"/>
<br/>
<p class = "slds-text-heading_small" style = "padding-right:190px;line-height: 40px;">Total Amount</p>
<br/>
</div>


</div>

<div class="slds-text-align_center slds-box slds-theme_shade slds-text-title_caps">
<apex:commandLink value="To shoping" action="{!getPage}" styleClass="slds-button slds-button_neutral"/>
<apex:commandLink value="Buy" action="{!save}" styleClass="slds-button slds-button_brand"/>

</div>
</apex:form>
</apex:page>

На какой конкретно строке вылетает
Attempt to de-reference a null object

Если не знаешь как получить Stacktrace, изучай этот вопрос.

Dmitry Shnyrev
На какой конкретно строке вылетает
Attempt to de-reference a null object

на 79

То есть я правильно понимаю что вылетает вот здесь?

contact con = new contact (FirstName = firstname, LastName = lastname, Email = email);
conlist.add(con);
insert con;
return null;

Да. правильно. Добавил отдельную переменную соn для этого дела и объявил селект в конструкторе, последний метод убрал, вместо него добавил два в начале, ошибка пропала.

global class ProductListController {

// List of products wich are exist in the Warehouse (product table)
public List <Product_Table__c> existProduct { get{return [SELECT Id, Image_Url__c, Name, Product_Description__c, Unit_Price__c
FROM Product_Table__c ];} set; }


//String Search
public String searchContactEmail {get; set;}
public static Contact contact { get; set; }
public Contact con { get; set; }

// Id selected product click "Buy"
public Id selectedProductId { get; set; }
public Product_Table__c prod { get; set; }
// List selected product
public List<Product_Table__c> currentProductsDatail { get; set; }
public List<Product_Table__c> currentProductsOrder { get; set; }

// Constructor
public ProductListController (){

con = [SELECT Id, Email, FirstName, LastName FROM Contact LIMIT 1];

searchContactEmail = '';
currentProductsDatail = new List<Product_Table__c>();
}


public Contact getConField () {

return con;

}


public void updateCon () {

update con;

}

// Get new page "ProductDetails" and details selected product
public pageReference getPage(){

currentProductsDatail = [SELECT Id, Image_Url__c, Name, Product_Description__c, Unit_Price__c, Unit_Available__c
FROM Product_Table__c WHERE Id =: selectedProductId ];

pageReference ref = new pageReference('/apex/ProductDetails');
return ref;

}

public pageReference getPurcharePage (){
prod = [SELECT Id, Name, Unit_Price__c
FROM Product_Table__c WHERE Id =: selectedProductId ];

pageReference ref = new pageReference('/apex/PurchareProduct');

return ref;
}


public pageReference getProductListPage (){

pageReference ref = new pageReference('/apex/Product_List');
return ref;
}


@RemoteAction
global static Contact getContact(String searchContactEmail) {

contact = [SELECT Email, FirstName, LastName
FROM Contact
WHERE Email =:searchContactEmail];
return contact;

}


}

@RemoteAction

global static Contact getContact(String searchContactEmail) {

contact = [SELECT Email, FirstName, LastName
FROM Contact
WHERE Email =:searchContactEmail];
return contact;

}


}

Это статик метод, ты не объявил переменную contact.

DevNull
Это статик метод, ты не объявил переменную contact.

Так ошибок нет
Все ж работает.

DevNull
Это статик метод, ты не объявил переменную contact.

Но при вводе email контакта LastName и FirstName подтягиваютя без проблем.

Dmitry Shnyrev
DevNull
Это статик метод, ты не объявил переменную contact.

Так ошибок нет
Все ж работает.

Ну по крайней мере при нажатии на кнопку никаких error. Но когда update заменил на insert, то охохохо...

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_static.htm

Maxim Elets
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_static.htm

RemoteAction methods must be declared as static

Попрошу еще немного пояснения. Чтобы проверить себя, сдела вот такую штуку:

public with sharing class ContactController {

public Contact c { get; set; }

public List<Contact> samepage { get; set; }

public ContactController(){
c=new Contact();
}

public void save() {
insert c;


}

}

ну и страничка

<apex:page Controller="ContactController" >
<apex:form >

<apex:pageBlock title="Edit Contact">

<apex:pageBlockSection columns="1">
<apex:inputField value="{!c.FirstName}"/>
<apex:inputField value="{!c.LastName}"/>
<apex:inputField value="{!c.Email}"/>
<apex:inputField value="{!c.Birthdate}"/>
</apex:pageBlockSection>
<apex:pageBlockButtons >
<apex:commandButton action="{!save}" value="Save"/>
</apex:pageBlockButtons>

</apex:pageBlock>

</apex:form>
</apex:page>

Все работает, контакт вставляется. Как только пытаюсь сделать с slds, и <apex:inputField меняю на просто <input>, то вылетает ошибка, типа lastname не может быть пустым. Получается я ничего не вставляю, и в value="" ничего не передается. Это какая-то фишка с slds? или нужно использовать что-то другое?????:(:(:(:(:(:(:(:(

pazik36
<apex:inputField меняю на просто <input>,

Очень странное решение!
apex:inputField это не просто input который пишется по другому. Это серьезный виджет на который завязана куча логики для того чтобы передать информацию из VF в Apex.
Поменять его на просто <input> означает просто взять и выкинуть большой кусок VF и надеяться что все будет также работать.
Конечно поэтому и "вылазит ошибка типа lastname не может быть пустым". Это поле на контакте Required а ты ничего туда не передаешь.
Ради эксперимента возьми и просто удали со страницы все apex:inputField (а не заменяй на <input>) и посмотри будет так же ошибка.

Dmitry Shnyrev
pazik36
<apex:inputField меняю на просто <input>,

Очень странное решение!
apex:inputField это не просто input который пишется по другому. Это серьезный виджет на который завязана куча логики для того чтобы передать информацию из VF в Apex.
Поменять его на просто <input> означает просто взять и выкинуть большой кусок VF и надеяться что все будет также работать.
Конечно поэтому и "вылазит ошибка типа lastname не может быть пустым". Это поле на контакте Required а ты ничего туда не передаешь.
Ради эксперимента возьми и просто удали со страницы все apex:inputField (а не заменяй на <input>) и посмотри будет так же ошибка.

Полностью согласен, эксперимент данный также провел. Но на странице с slds мне не дает использовать <apex:inputField>. А загуглив apex:inputField slds получил вот такое https://www.lightningdesignsystem.com/components/input/ . Поэтому для вывода инфы еще работало, а как дошло дело до inserta, так и началась непонятка.

pazik36
А загуглив apex:inputField slds получил вот такое https://www.lightningdesignsystem.com/components/input/

Какой-то у тебя гугл неправильный. Ты не заметил что на странице нет ни одного упоминания apex:inputField. Почему ты решил что эта страница тебе поможет?

pazik36
Но на странице с slds мне не дает использовать <apex:inputField>

Вот это вообще не понятно. Что значит страница с slds и что значит не дает использовать?

Dmitry Shnyrev
Вот это вообще не понятно. Что значит страница с slds и что значит не дает использовать?

Это значит, что я это делаю на странице, где есть тег <apex:slds/> . А не дает, это значит, что выскакивает такая ошибка Unsupported attribute class in <apex:inputField>.

<apex:page controller="ProductListController"  >

<apex:slds />
<apex:form >


<script type="text/javascript">
function getRemoteContact() {

var searchContactEmail = document.getElementById('contactsearch').value;

Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.ProductListController.getContact}',
searchContactEmail,
function(result, event){
if(event.status){

document.getElementById('remoteConFname').value = result.FirstName;

document.getElementById('remoteConLname').value = result.LastName;



} else if (event.type == 'exception'){
document.getElementById(
"responseErrors"
).innerHTML = event.message = "<br/>\n<pre>" + event.where + "</pre>";
}else{
document.getElementById(
"responseErrors"
).innerHTML = event.message;
}
},
{escape:true}

);
}

</script>


<div class="slds-grid slds-wrap slds-box slds-theme_shade ">
<div class="slds-text-align_center slds-text-title_caps slds-size_1-of-2">
<span class= "slds-page-header__title slds truncate">Contact information</span>
</div>
<div class="slds-text-align_center slds-text-title_caps slds-size_1-of-2">
<span class= "slds-page-header__title slds truncate">Product information</span>

</div>
</div>

<div class="slds-grid" >
<div class="slds-text-align_center slds-size_1-of-2">

<br/>
<label class="slds-text-heading_small" for="Email" style="padding-left:52px">Email</label>
<apex:inputField id="contactsearch" class="slds-input" type="text" name="Email" style = "width: 30%;" value="{!con.Email}" />
<br/><br/>
<label class="slds-text-heading_small" for="FirstName" style="padding-left:12px">First Name</label>
<input class="slds-input" name="FirstName" style="width: 30%;" type="text" id="remoteConFname" placeholder="" value="{!con.FirstName}" />
<br/><br/>
<label class="slds-text-heading_small" for="LastName" >Last Name <abbr class="slds-required" title="required">* </abbr> </label>
<input class="slds-input" name="LastName" style="width: 30%;" type="text" id="remoteConLname" placeholder="" value="{!con.LastName}" />

<br/><br/>

</div>

<div class="slds-text-align_center slds-size_1-of-2">
<br/>
<p class = "slds-text-heading_small" style = "padding-right:200px">Product Name &nbsp; {!prod.Name}</p>
<br/>
<p class = "slds-text-heading_small" style = "padding-right:125px">Cost &nbsp; {!prod.Unit_Price__c}$ </p>
<br/>
<label class = "slds-text-heading_small" for="UnitCount" >Unit Count</label>
<input class = "slds-input" id="UnitCount" name="UnitCount" style = "width: 30%;"/>
<br/>
<p class = "slds-text-heading_small" style = "padding-right:190px;line-height: 40px;">Total Amount</p>
<br/>
</div>

</div>

<div class="slds-text-align_center slds-box slds-theme_shade slds-text-title_caps">
<apex:commandLink value="To shoping" action="{!getPage}" styleClass="slds-button slds-button_neutral"/>
<apex:commandLink value="Buy" action="{!save}" styleClass="slds-button slds-button_brand"/>
<button onclick = "getRemoteContact()">get contact</button>

</div>
</apex:form>
</apex:page>

Вот что я имел ввиду)

56 строка.

Dmitry Shnyrev
Вот это вообще не понятно. Что значит страница с slds и что значит не дает использовать?

Правильнее сказать этим я имел ввиду.!!!!

pazik36
Unsupported attribute class in <apex:inputField>

Раcсказываю как эту ошибку чинить. Она не имеет никакого отношения к slds.
"Unsupported attribute ... in <apex" означает что данный apex:... тег не поддерживает атрибут
Решается это просто поиском подходяшего который поддерживается
вот к примеру страница apex:inputField
https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_inputField.htm
там внизу большая таблица с поддерживаемыми атрибутами.
попробуй найти там атрибут "class"
(если не получится найти даю подскажку "styleClass")

Это первая ошибка начинающих - нельзя смешивать знания HTML и Visualforce. Хоть теги VF и похожи на обычные HTML, но это совсем не HTML который рендерится браузером и понимается JS. VF парсится еще на стороне SF и все теги VF заменяются на большие сложные блоки HTML еще до отправки в браузер. Это можно увидеть в консоли браузера если открыть исходный код страницы.

Dmitry Shnyrev
Это первая ошибка начинающих - нельзя смешивать знания HTML и Visualforce. Хоть теги VF и похожи на обычные HTML, но это совсем не HTML который рендерится браузером и понимается JS. VF парсится еще на стороне SF и все теги VF заменяются на большие сложные блоки HTML еще до отправки в браузер. Это можно увидеть в консоли браузера если открыть исходный код страницы.

Ухххх.Спасибо,получилось.!!! Честно говоря копировал из https://www.lightningdesignsystem.com/components/input/ и даже не задумывался!

pazik36
даже не задумывался!

Это и есть САМАЯ ГЛАВНАЯ проблема начинающих! Копипастить от балды.
В IT ничего не бывает просто так. Каждая команда, каждый символ имеет какой-то смысл. И этот смысл надо понимать чтобы писать код. Просто так копипастить куски кода ничего не даст. Разве что поиграться с тестовым заданием. Ни один реальный проект не заработает по такому принципу. Нужно понимать просто ВСЕ в коде!!!!!
А чтобы понимать ВСЕ надо читать официальную документацию в первоисточнике!!! Никакие блоги, трейлхеды, stackoverflow не помогут стать программистами.
Вот к примеру то что надо изучить чтобы начать программировать на Visualforce
https://resources.docs.salesforce.com/218/latest/en-us/sfdc/pdf/salesforce_pages_developers_guide.pdf
И не пролистать, а изучить. Как учат предмет в универе, с конспектом. И делается это не за день, неделю и даже возможно не за месяц.
А таких документаций в Salesforce дофуя!
https://developer.salesforce.com/docs/
И для чистого программиста их минимум 10. Но чистый программист без знания самой платформы Salesforce ничего не стоит, а значит надо изучать все!

Кандидат на Junior должен минимум уметь ориентироваться в этой документации и знать как найти в ней нужную информацию. Это как троечник на экзамене. Он минимум должен уметь найти ответ на билет имея под рукой всю литературу. Тот кто хочет стать Seniоr и выше должен отвечать на 4-5 (по пятибальной шкале) используя свой конспект или чисто голову.

Ох надеюсь я понятно объяснил что такое программист и как надо им становиться?

Dmitry Shnyrev
Ох надеюсь я понятно объяснил что такое программист и как надо им становиться? :D

Яснее некуда)

Interesting information? Help us, post link to social media..