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

Как правильно сделать сортировку+пагинацию списка в VisualForce странице

Добрый день всем.
Я только начинаю изучение SalesForce, и мне нужно выполнить тестовое задание для одной компании.
Согласно заданию, требуется сделать список контактов с пагинацией, возможностью поиска, и сортировкой по столбцу.
Я сделал пагинацию, поиск и сортировку, соединив примеры отсюда.

http://blog.jeffdouglas.com/2010/07/13/building-a-dynamic-search-page-in-visualforce/
http://blog.jeffdouglas.com/2009/07/14/visualforce-page-with-pagination/

Используется контроллер и запрос, формируемый динамически

queryString = 'select Id, Name, Email, Contact_Level__c, AccountId, OwnerId, CreatedById, CreatedDate from CONTACT where Name LIKE \'%' + filter + '%\'' + ' order by ' + sortField + ' ' + sortDir + ' limit 10000';

Все работает, но не так как хотелось бы.

Допустим, изначально сортировка контактов идет по имени, и контакты выводятся на несколько страниц.
Пользователь перешел на вторую страницу и решил сделать сортировку по e-mail.
Он щелкнул по наименованию столбца, и контроллер заново выполнил запрос с сортировкой по полю Email.
При этом, естественно, полностью поменялся порядок записей в выборке, и пользователь теперь после сортировки на второй странице (собственно и на любой другой), увидит иной набор записей, чем был до этого.
Например, было отсортировано по алфавиту

Иванов vasya@gmail.com
Петров kicker7852@mail.ru
Сидоров blackman777@ya.ru

А после сортировки по e-mail стало

Пупкин amega@hotbox.ru
Сидоров blackman777@ya.ru
Степанов camer111@mail.ru

Хотя правильно было бы

Сидоров blackman777@ya.ru
Петров kicker7852@mail.ru
Иванов vasya@gmail.com

Если бы не было пагинации и все записи были на одной странице, то все было бы логично, выборка полностью пересортирована, и это правильно.

А вот при пагинации полная пересортировка приводит к нехорошему эффекту.

Вопрос.

Можно ли как-то сделать на стороне контроллера, или другим способом, чтобы записи пересортировывались на конкретной странице, не меняя выборку в целом, и при этом пересортировка при переходе на другую страницу также работала бы, но набор записей на каждой странице при этом сохранялся исходный (до сортировки)?

Добрый день всем.
Я только начинаю изучение SalesForce, и мне нужно выполнить тестовое задание для одной компании. 
Согласно заданию, требуется сделать список контактов с пагинацией, возможностью поиска, и сортировкой по столбцу. 
Я сделал пагинацию, поиск и сортировку, соединив примеры отсюда. 

http://blog.jeffdouglas.com/2010/07/13/building-a-dynamic-search-page-in-visualforce/
http://blog.jeffdouglas.com/2009/07/14/visualforce-page-with-pagination/

Используется контроллер и запрос, формируемый динамически

queryString = 'select  Id, Name, Email, Contact_Level__c, AccountId, OwnerId, CreatedById, CreatedDate from CONTACT where Name LIKE \'%' + filter + '%\''  + ' order by ' + sortField + ' ' + sortDir +   ' limit 10000';

Все работает, но не так как хотелось  бы. 

Допустим, изначально сортировка контактов идет по имени, и контакты выводятся на несколько страниц. 
Пользователь перешел на вторую страницу и решил сделать сортировку по e-mail.
Он щелкнул по наименованию столбца, и контроллер заново выполнил запрос с сортировкой по полю Email. 
При этом, естественно, полностью поменялся порядок записей в выборке, и пользователь теперь после сортировки на второй странице (собственно и на любой другой), увидит иной набор записей, чем был до этого. 
Например, было отсортировано по алфавиту

Иванов		vasya@gmail.com
Петров		kicker7852@mail.ru
Сидоров	        blackman777@ya.ru

А после сортировки по e-mail стало

Пупкин		amega@hotbox.ru
Сидоров	        blackman777@ya.ru
Степанов	camer111@mail.ru

Хотя правильно было бы

Сидоров	        blackman777@ya.ru
Петров		kicker7852@mail.ru
Иванов		vasya@gmail.com

Если бы не было пагинации и все записи были на одной странице, то все было бы логично, выборка полностью пересортирована, и это правильно. 

А вот при пагинации полная пересортировка приводит к нехорошему эффекту. 

Вопрос. 

Можно ли как-то сделать на стороне контроллера, или другим способом, чтобы записи пересортировывались на конкретной странице, не меняя выборку в целом, и при этом пересортировка при переходе на другую страницу также работала бы, но набор записей на каждой странице при этом сохранялся исходный (до сортировки)?

beginner
Можно ли как-то сделать на стороне контроллера, или другим способом, чтобы записи пересортировывались на конкретной странице, не меняя выборку в целом, и при этом пересортировка при переходе на другую страницу также работала бы, но набор записей на каждой странице при этом сохранялся исходный (до сортировки)?

Можно, все зависит от того как выглядит твой контроллер. Причем вариантов очень много как это реализовать.
Можно просто сортировать на фронтенде используя любую либу.
Можно сделать метод, в котором ты сортируешь конкретный набор данных который у тебя выводится(implements Comparable к примеру)
и тд

PS: И мне кажется что тот вариант(первый)который пересортировывает все - правильный. Просто посмотри как работает стандартная сортировка на контактах у самого Salesforce. Она не сортирует какие-то 3 значения на странице.

[quote="beginner"]Можно ли как-то сделать на стороне контроллера, или другим способом, чтобы записи пересортировывались на конкретной странице, не меняя выборку в целом, и при этом пересортировка при переходе на другую страницу также работала бы, но набор записей на каждой странице при этом сохранялся исходный (до сортировки)?[/quote]

Можно, все зависит от того как выглядит твой контроллер. Причем вариантов очень много как это реализовать.
Можно просто сортировать на фронтенде используя любую либу.
Можно сделать метод, в котором ты сортируешь конкретный набор данных который у тебя выводится(implements Comparable к примеру)
и тд

PS: И мне кажется что тот вариант(первый)который пересортировывает все - правильный. Просто посмотри как работает стандартная сортировка на контактах у самого Salesforce. Она не сортирует какие-то 3 значения на странице.



При изменении сортировки логичнее было бы скидывать пагинацию в 0, (то есть ставить страницу 0).
Я даже представить не могу что ожидает увидеть и что увидит пользователь, который находится на 20-й странице при изменении сортировки с Name на Email. Мне кажется в твоем случае так и происходит. Ты ожидаешь что должна сортироваться непосредственно сама 20 страница (записи в пределах 20-й страницы) но вообще сортируется ВСЕ контакты в базе и тебе просто показывается срез этой сортировки для 20-й страницы.

При изменении сортировки логичнее было бы скидывать пагинацию в 0, (то есть ставить страницу 0).
Я даже представить не могу что ожидает увидеть и что увидит пользователь, который находится на 20-й странице при изменении сортировки с Name на Email. Мне кажется в твоем случае так и происходит. Ты ожидаешь что должна сортироваться непосредственно сама 20 страница (записи в пределах 20-й страницы) но вообще сортируется ВСЕ контакты в базе и тебе просто показывается срез этой сортировки для 20-й страницы. 

пагинация довольно интересная тема

я думаю, что тебе можно оставить бек-энд пагинацию на базе стандартного контроллера как есть (есть нет угрозы что общее число записей не грохнет ViewState лимит, т.к. ApexPages.StandardSetController con по моему содержит сразу все выквериные записи и прямиком идет в ViewState)

а вот с сортировкой "на месте" только той части записей, что попали на страницу, все очень просто - используй JS плагин для таблиц. Там же ты быстро найдешь плагины для фронт-энд пагинация (когда все записи выкладываются на страницу разом, а плагин просто собирает их в пагинированную на месте таблицу), но это будет уже другой разговор.

пагинация довольно интересная тема

я думаю, что тебе можно оставить бек-энд пагинацию на базе стандартного контроллера как есть (есть нет угрозы что общее число записей не грохнет ViewState лимит, т.к. ApexPages.StandardSetController con по моему содержит сразу все выквериные записи и прямиком идет в ViewState)

а вот с сортировкой "на месте" только той части записей, что попали на страницу, все очень просто - используй JS плагин для таблиц. Там же ты быстро найдешь плагины для фронт-энд пагинация (когда все записи выкладываются на страницу разом, а плагин просто собирает их в пагинированную на месте таблицу), но это будет уже другой разговор.

Всем спасибо.
Оставил контроллерную пагинацию, а сортировку на странице сделал через JQuery.
Тут есть хороший пример сортировки.

https://developer.salesforce.com/forums/?id=906F0000000BLV8IAO

Есть некоторые нюансы с ее "прикручиванием", но все получилось в итоге.
Контроллерная сортировка думаю тоже имеет право на существование, но скорее всего в задании имелась ввиду как раз сортировка через JQuery.

Всем спасибо. 
Оставил контроллерную пагинацию, а сортировку на странице сделал через JQuery.
Тут есть хороший пример сортировки.

https://developer.salesforce.com/forums/?id=906F0000000BLV8IAO

Есть некоторые нюансы с ее "прикручиванием", но все получилось в итоге. 
Контроллерная сортировка думаю тоже имеет право на существование, но скорее всего в задании имелась ввиду как раз сортировка через JQuery. 

В итоге смешал мух с котлетами.

Получается ты сортируешь в jQuery только записи которые тебе вернулись для одной текущей страницы?

А если мне надо отсортировать все записи по email и посмотреть что находится на третьей странице?

Какая сортировка в контроллере используется?

В итоге смешал мух с котлетами.

Получается ты сортируешь в jQuery только записи которые тебе вернулись для одной текущей страницы?

А если мне надо отсортировать все записи по email и посмотреть что находится на третьей странице?

Какая сортировка в контроллере используется?

Проще говоря!

Сортировка должна идти всегда ДО пагинации, а НЕ ПОСЛЕ!

Проще говоря!

Сортировка должна идти всегда ДО пагинации, а НЕ ПОСЛЕ!

beginner
Контроллерная сортировка думаю тоже имеет право на существование, но скорее всего в задании имелась ввиду как раз сортировка через JQuery.

Ни одно нормальное задание никогда не будет содержать требование прикрутить стороннюю библиотеку.
Видя в проектах тонны JQuery костылей прикрученных к visualforce странице и находящихся прямо на ней, я уже на эту библиотеку смотреть не могу.
Есть 3 нормальные опции для выполнения задания:
1) только visualforce
2) только lightning, если функционала visualforce не хватает и нужно прикручивать костыли на стандартные visualforce компоненты
3) visualforce + какой-нибудь фрэймворк типа Angular. Visualforce будет тут использоваться только как оболочка.
п.с. сортировка как и пагинация должны выполняться запросом в базу, а не прямо на странице по существующему массиву данных.

[quote="beginner"]Контроллерная сортировка думаю тоже имеет право на существование, но скорее всего в задании имелась ввиду как раз сортировка через JQuery. [/quote]

Ни одно нормальное задание никогда не будет содержать требование прикрутить стороннюю библиотеку.
Видя в проектах тонны JQuery костылей прикрученных к visualforce странице и находящихся прямо на ней, я уже на эту библиотеку смотреть не могу.
Есть 3 нормальные опции для выполнения задания:
1) только visualforce
2) только lightning, если функционала visualforce не хватает и нужно прикручивать костыли на стандартные visualforce компоненты
3) visualforce + какой-нибудь фрэймворк типа Angular. Visualforce будет тут использоваться только как оболочка.
п.с. сортировка как и пагинация должны выполняться запросом в базу, а не прямо на странице по существующему массиву данных.

Хорошо, что есть на этом форуме неравнодушные люди, готовые всегда объяснить что правильно, а что нет.
Поскольку клиент всегда прав, то я спросил фирму, как нужно сделать.
Ответ - сортировку реализовать через контроллер без JQuery.

Хорошо, что есть на этом форуме неравнодушные люди, готовые всегда объяснить что правильно, а что нет. ;)
Поскольку клиент всегда прав, то я спросил фирму, как нужно сделать. 
Ответ - сортировку реализовать через контроллер без JQuery.

beginner
Хорошо, что есть на этом форуме неравнодушные люди, готовые всегда объяснить что правильно, а что нет.
Поскольку клиент всегда прав, то я спросил фирму, как нужно сделать.
Ответ - сортировку реализовать через контроллер без JQuery.

Увольняйся :))))))

АА
Блин, прочитал что надо jQuery юзать, а потом перечитал

[quote="beginner"]Хорошо, что есть на этом форуме неравнодушные люди, готовые всегда объяснить что правильно, а что нет. ;)
Поскольку клиент всегда прав, то я спросил фирму, как нужно сделать. 
Ответ - сортировку реализовать через контроллер без JQuery.[/quote]
[s]Увольняйся :))))))[/s]

АА
Блин, прочитал что надо jQuery юзать, а потом перечитал  :)





О! Млин! У нас зачеркивание есть? Прикольная фича когда надо поправиться.

О! Млин! У нас зачеркивание есть? Прикольная фича когда надо поправиться.

Dmitry Shnyrev
О! Млин! У нас зачеркивание есть? Прикольная фича когда надо поправиться.

у тебя нет) это такой эдакий хак))
[_s]тут текст[_s]
подчеркивания убрать)

[quote="Dmitry Shnyrev"]О! Млин! У нас зачеркивание есть? Прикольная фича когда надо поправиться.[/quote]
у тебя нет) это такой эдакий хак))
[_s]тут текст[_s]
подчеркивания убрать)

Несколько советов:
1. Экранируйте полученные от пользователя данные (escapeSingleQuotes в помощь) - в оригинальном примере при построении запроса это было, у вас вроде как нет.
2. ApexPages.StandardSetController - сильно дохера ограничений имеет, да и работает не сильно шустро плюс, Den Brown по-моему прав, сильно нагрузит viewstate
3. Используйте аттрибут readonly и сможете обойти ограничение на кол-во записей
4. На страницу выгружайте небольшое кол-во записей, штук 100 реально почти всегда будет достаточно
5. Т.к. задача чисто показать возможность постраничного просмотра - используйте transient для переменной которая будет содержать record'ы, это облегчит viewstate и ускорит работу
6. Прийдётся реализовать свой собственный механизм постраничного перехода, это в принципе не сложно

Несколько советов:
1. Экранируйте полученные от пользователя данные (escapeSingleQuotes в помощь) - в оригинальном примере при построении запроса это было, у вас вроде как нет.
2. ApexPages.StandardSetController - сильно дохера ограничений имеет, да и работает не сильно шустро плюс, Den Brown по-моему прав, сильно нагрузит viewstate
3. Используйте [url=https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_ReadOnly.htm#!]аттрибут readonly[/url] и сможете обойти ограничение на кол-во записей
4. На страницу выгружайте небольшое кол-во записей, штук 100 реально почти всегда будет достаточно
5. Т.к. задача чисто показать возможность постраничного просмотра - используйте transient для переменной которая будет содержать record'ы, это облегчит viewstate и ускорит работу
6. Прийдётся реализовать свой собственный механизм постраничного перехода, это в принципе не сложно

Спасибо, полученные советы буду использовать уже в работе, так тестовое сделано и принято без замечаний, также получен и принят job offer.

Спасибо, полученные советы буду использовать уже в работе, так тестовое сделано и принято без замечаний, также получен и принят job offer. 

beginner
Спасибо, полученные советы буду использовать уже в работе, так тестовое сделано и принято без замечаний, также получен и принят job offer.

Добрый день, делаю что-то похожее, а возможно тоже самое. Поэтому возник вопрос по приклеивания кнопки удаления к каждой строке. Делаю такую штуку:
<apex:column >
<apex:commandButton action="{!URLFOR($Action.Contact.Delete, Contact.Id)}" value="Del"/>
</apex:column>

Но почему-то никак!

[quote="beginner"]Спасибо, полученные советы буду использовать уже в работе, так тестовое сделано и принято без замечаний, также получен и принят job offer.[/quote]
Добрый день, делаю что-то похожее, а возможно тоже самое. Поэтому возник вопрос по приклеивания кнопки удаления к каждой строке. Делаю такую штуку:
<apex:column >
<apex:commandButton action="{!URLFOR($Action.Contact.Delete, Contact.Id)}" value="Del"/>
</apex:column>

Но почему-то никак!

pazik36
beginner
Спасибо, полученные советы буду использовать уже в работе, так тестовое сделано и принято без замечаний, также получен и принят job offer.

Добрый день, делаю что-то похожее, а возможно тоже самое. Поэтому возник вопрос по приклеивания кнопки удаления к каждой строке. Делаю такую штуку:
<apex:column >
<apex:commandButton action="{!URLFOR($Action.Contact.Delete, Contact.Id)}" value="Del"/>
</apex:column>

Но почему-то никак!


я просто к тому, что вот эта штука работает на ура!!!
<apex:commandbutton action="{!URLFOR($Action.Contact.NewContact)}" value="New Contact"/>

[quote="pazik36"][quote="beginner"]Спасибо, полученные советы буду использовать уже в работе, так тестовое сделано и принято без замечаний, также получен и принят job offer.[/quote]
Добрый день, делаю что-то похожее, а возможно тоже самое. Поэтому возник вопрос по приклеивания кнопки удаления к каждой строке. Делаю такую штуку:
<apex:column >
<apex:commandButton action="{!URLFOR($Action.Contact.Delete, Contact.Id)}" value="Del"/>
</apex:column>

Но почему-то никак![/quote]


я просто к тому, что вот эта штука работает на ура!!!
<apex:commandbutton action="{!URLFOR($Action.Contact.NewContact)}" value="New Contact"/>

pazik36
Но почему-то никак!

Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm

[quote="pazik36"]Но почему-то никак![/quote]
Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm

Dmitry Shnyrev
pazik36
Но почему-то никак!

Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm

Я имел ввиду что-то вроде этого https://salesforce-developer.ru/forum/topic-delete-function. Да все сохраняется!!

[quote="Dmitry Shnyrev"][quote="pazik36"]Но почему-то никак![/quote]
Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm[/quote]

Я имел ввиду что-то вроде этого https://salesforce-developer.ru/forum/topic-delete-function. Да все сохраняется!!

pazik36
Dmitry Shnyrev
pazik36
Но почему-то никак!

Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm

Я имел ввиду что-то вроде этого https://salesforce-developer.ru/forum/topic-delete-function Да все сохраняется!!

[quote="pazik36"][quote="Dmitry Shnyrev"][quote="pazik36"]Но почему-то никак![/quote]
Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm[/quote]

Я имел ввиду что-то вроде этого https://salesforce-developer.ru/forum/topic-delete-function Да все сохраняется!![/quote]

pazik36
pazik36
Dmitry Shnyrev
pazik36
Но почему-то никак!

Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm

Я имел ввиду что-то вроде этого https://salesforce-developer.ru/forum/topic-delete-function Да все сохраняется!!


Да и кстати,удается строка как с кнопкой, так и с линк, при наличие apex param конечно, что странно!!! Но только rerender почему-то не работает, строка пропадает только после ручного обновления!

[quote="pazik36"][quote="pazik36"][quote="Dmitry Shnyrev"][quote="pazik36"]Но почему-то никак![/quote]
Сложно сказать почему никак если не понятно что "никак".
У вас ошибка? У вас не сохраняется Visualforce Page? Вас редиректит на другую страницу(урл)?
Что "никак"?
Вообще такие штуки делаются через кастомные actions(методы) в контроллере страницы, а не через стандартные страницы.
Но! Чтобы показать свое мастерство я бы вообще советовал сделать удаление через REST API.
Тут вообще одна строка кода
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_delete_record.htm[/quote]

Я имел ввиду что-то вроде этого https://salesforce-developer.ru/forum/topic-delete-function Да все сохраняется!![/quote][/quote]
Да и кстати,удается строка как с кнопкой, так и с линк, при наличие apex param конечно, что странно!!! Но только rerender почему-то не работает, строка пропадает только после ручного обновления! 

Добрый день, делаю что-то похожее, а возможно тоже самое. Поэтому возник вопрос по приклеивания кнопки удаления к каждой строке. Делаю такую штуку:
<apex:column >
<apex:commandButton action="{!URLFOR($Action.Contact.Delete, Contact.Id)}" value="Del"/>
</apex:column>

Но почему-то никак!

Похоже, что тоже самое и что я делал:)
Во-первых, хочу предупредить что компания, куда вы хотите устроиться, далеко не идеальна, подойдет только для старта карьеры на Salesforce.
Во-вторых, с удалением нужно немного поковыряться.
Я делал через JS функцию, которая вызывает Apex-функцию, описанную на VF-странице, и та в свою очередь запускает метод из контроллера. Обновление делал через повторный запрос к данным в методе контроллера, рефреш на странице делается стандартно через указание области рендеринга.
Не помню где брал информацию об APEX-функциях.
Примерно так.

<!-- APEX fuction to delete contact-->
<apex:actionFunction name="deleteContact" action="{!deleteContact}" rerender="ContactListBox, errors">
<apex:param name="contactId" value="" />
</apex:actionFunction>

REST API - ну это совсем круто для новичка :)

[quote]
Добрый день, делаю что-то похожее, а возможно тоже самое. Поэтому возник вопрос по приклеивания кнопки удаления к каждой строке. Делаю такую штуку:
<apex:column >
<apex:commandButton action="{!URLFOR($Action.Contact.Delete, Contact.Id)}" value="Del"/>
</apex:column>

Но почему-то никак![/quote]

Похоже, что тоже самое и что я делал:)
Во-первых, хочу предупредить что компания, куда вы хотите устроиться, далеко не идеальна, подойдет только для старта карьеры на Salesforce.
Во-вторых, с удалением нужно немного поковыряться. 
Я делал через JS функцию, которая вызывает Apex-функцию, описанную на VF-странице, и та в свою очередь запускает метод из контроллера. Обновление делал через повторный запрос к данным в методе контроллера, рефреш на странице делается стандартно через указание области рендеринга. 
Не помню где брал информацию об APEX-функциях. 
Примерно так. 

 <!-- APEX fuction to delete contact-->       
 <apex:actionFunction name="deleteContact" action="{!deleteContact}" rerender="ContactListBox, errors">
      <apex:param name="contactId" value="" />
 </apex:actionFunction>      

REST API - ну это совсем круто для новичка :)

Спасибо, но прикрутил линк из того же примера по ссылке и все работает.

То, что для старта - так это мне и нужно!!

REST API - пока набор букв для меня)

Спасибо, но прикрутил линк из того же примера по ссылке и все работает.

То, что для старта - так это мне и нужно!!

REST API - пока набор букв для меня)

pazik36
Спасибо, но прикрутил линк из того же примера по ссылке и все работает.

То, что для старта - так это мне и нужно!!

REST API - пока набор букв для меня)

а вот пагинация из Ваших ссылок не откликается!

[quote="pazik36"]Спасибо, но прикрутил линк из того же примера по ссылке и все работает.

То, что для старта - так это мне и нужно!!

REST API - пока набор букв для меня)[/quote]

а вот пагинация из Ваших ссылок не откликается!

pazik36
pazik36
Спасибо, но прикрутил линк из того же примера по ссылке и все работает.

То, что для старта - так это мне и нужно!!

REST API - пока набор букв для меня)

а вот пагинация из Ваших ссылок не откликается!

А не идеальность в чем заключается, если не секрет конечно????: отношение, коллектив, зп, перспективы???

[quote="pazik36"][quote="pazik36"]Спасибо, но прикрутил линк из того же примера по ссылке и все работает.

То, что для старта - так это мне и нужно!!

REST API - пока набор букв для меня)[/quote]

а вот пагинация из Ваших ссылок не откликается![/quote]

А не идеальность в чем заключается, если не секрет конечно????: отношение, коллектив, зп, перспективы???

Вопрос: Есть контроллер и страница соответственно. Приведены ниже. Почему не срабатывает отображение по выбранному количеству строк (5,10 и т.д.). То, что нету методов на "предыдущий следующий " это понятно и не суть. Оговорюсь сразу, что данный вариант нашел в интернете. Предполагаю, что не в том месте находиться ApexPages.StandardSetController.

<apex:page Controller="ContactsManagerController">
<apex:form id="form" >

<apex:pageBlock id="pbId">
<apex:actionFunction name="refreshPageSize" action="{!refreshPageSize}" status="fetchStatus" reRender="pbId"/>
Search: &nbsp;
<apex:inputText value="{!SearchContact}" label="Search"/>

<apex:commandButton action="{!startSearch}" value="Search"/>
&nbsp;
<apex:commandbutton action="{!URLFOR($Action.Contact.NewContact)}" value="New Contact"/>


<apex:pageBlockSection title="Contact information" columns="1" >

<apex:pageBlockTable value="{!contactList}" var="item" id="pbId">

<apex:column >
<apex:outputLink title="" value="/{!item.id}/e?retURL=/apex/{!$CurrentPage.Name}" style="font-weight:bold">Edit</apex:outputLink>&nbsp;|&nbsp;
<a href="javascript:if (window.confirm('Are you sure?')) deleterecord('{!item.Id}');" style="font-weight:bold">Del</a>

</apex:column>

<apex:column headerValue="Name" >
<a href="/{item.Id}" target="_blank">{!item.Name}</a>
<apex:facet name="header">
<apex:commandLink action="{! getsortcontactsname }"
reRender="pbId">Name
</apex:commandLink>
</apex:facet>
</apex:column>

<apex:column headerValue="Email" value="{!item.Email}">
<apex:facet name="header">
<apex:commandLink action="{! getsortcontactsEmail }"
reRender="pbId">Email
</apex:commandLink>
</apex:facet>
</apex:column>

<apex:column headerValue="Contact Level" value="{!item.Contact_Level__c}">

<apex:facet name="header">
<apex:commandLink action="{! getsortcontactsLevel }"
reRender="pbId">Contact Level
</apex:commandLink>
</apex:facet>
</apex:column>


<apex:column headerValue="Account" value="{!item.AccountId}">
<apex:facet name="header">
<apex:commandLink action="{! getsortaccount }"
reRender="pbId">Account
</apex:commandLink>
</apex:facet>
</apex:column>

<apex:column headerValue="Owner" value="{!item.OwnerId}">
<apex:facet name="header">
<apex:commandLink action="{! getsortOwner }"
reRender="pbId">Owner
</apex:commandLink>
</apex:facet>
</apex:column>

<apex:column headerValue="Created By" value="{!item.CreatedById}">
<apex:facet name="header">
<apex:commandLink action="{! getsortCreatedBy }"
reRender="pbId">Created By
</apex:commandLink>
</apex:facet>
</apex:column>

<apex:column headerValue="Created Date" value="{!item.CreatedDate}">
<apex:facet name="header">
<apex:commandLink action="{! getsortCreatedDate }"
reRender="pbId">Created Date
</apex:commandLink>
</apex:facet>
</apex:column>

</apex:pageBlockTable>



<apex:panelGrid columns="8">

<apex:selectList value="{!size}" multiselect="false" size="1" onchange="refreshPageSize();">
<apex:selectOptions value="{!paginationSizeOptions}"/>
</apex:selectList>



<apex:commandButton status="fetchStatus" reRender="pbId" value="First" action="{!setCon.first}" disabled="{!!setCon.hasPrevious}" title="First Page"/>

<apex:commandButton status="fetchStatus" reRender="pbId" value="Previous" action="{!setCon.previous}" disabled="{!!setCon.hasPrevious}" title="Previous Page"/>

<apex:commandButton status="fetchStatus" reRender="pbId" value="Next" action="{!setCon.next}" disabled="{!!setCon.hasNext}" title="Next Page"/>

<apex:commandButton status="fetchStatus" reRender="pbId" value="Last" action="{!setCon.last}" disabled="{!!setCon.hasNext}" title="Last Page"/>

<apex:outputText >{!(setCon.pageNumber * size)+1-size}-{!IF((setCon.pageNumber * size)>noOfRecords, noOfRecords,
(setCon.pageNumber * size))} of {!noOfRecords}
</apex:outputText>

<apex:outputPanel >
<apex:actionStatus id="fetchStatus" >
<apex:facet name="start" >
<img src="/img/loading.gif" />
</apex:facet>
</apex:actionStatus>
</apex:outputPanel>


</apex:panelGrid>

</apex:pageBlockSection>
<apex:actionFunction action="{!deleterecord}" name="deleterecord" reRender="form" >
<apex:param name="contacts" value="" assignTo="{!SelectedContactId}" />
</apex:actionFunction>

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

public with sharing  class ContactsManagerController {

public List<Contact> contactList {get;set;}
public String SearchContact {get; set;}
Public Integer size{get;set;}
Public Integer noOfRecords{get; set;}

public string SelectedContactId { get; set; }

public List<SelectOption> paginationSizeOptions{get;set;}

public ContactsManagerController () {

size=10;
paginationSizeOptions = new List<SelectOption>();
paginationSizeOptions.add(new SelectOption('5','5'));
paginationSizeOptions.add(new SelectOption('10','10'));
paginationSizeOptions.add(new SelectOption('20','20'));
paginationSizeOptions.add(new SelectOption('50','50'));
paginationSizeOptions.add(new SelectOption('100','100'));

SearchContact = '';


String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c,'
+ 'Account.Name, Owner.Name, CreatedBy.Name,'
+ ' CreatedDate FROM Contact';

this.contactList = Database.query(contactqauery);


LoadData();

}

public ApexPages.StandardSetController setCon {

get {
if(setCon == null) {
setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
[select Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact]));
setCon.setPageSize(size);
noOfRecords = setCon.getResultSize();
}
return setCon;
}
set;
}

// Initialize setCon and return a list of record

public List<Contact> getcontact() {

return (List<Contact>) setCon.getRecords();
}


//Changes the size of pagination
public PageReference refreshPageSize() {
setCon.setPageSize(size);
return NULL;
}








public void startSearch () {
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c,'
+'Account.Name, Owner.Name, CreatedBy.Name,'
+' CreatedDate FROM Contact '
+' WHERE LastName =:SearchContact OR FirstName =:SearchContact';
this.contactList = Database.query(contactqauery);

}


public void getsortcontactsname () {
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact ORDER BY Name ASC';
this.contactList = Database.query(contactqauery);
}

public void getsortcontactsEmail (){
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact ORDER BY Email ASC';
this.contactList = Database.query(contactqauery);
}

public void getsortcontactsLevel (){
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact ORDER BY Email ASC';
this.contactList = Database.query(contactqauery);
}

public void getsortaccount (){
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact ORDER BY Account.Name ASC';
this.contactList = Database.query(contactqauery);
}

public void getsortOwner () {
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact ORDER BY Owner.Name ASC';
this.contactList = Database.query(contactqauery);
}

public void getsortCreatedBy (){
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact ORDER BY CreatedBy.Name ASC';
this.contactList = Database.query(contactqauery);
}


public void getsortCreatedDate () {
String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact WHERE CreatedDate < TODAY';
this.contactList = Database.query(contactqauery);
}


private void LoadData() {
contactList = [SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact LIMIT 10000];
}

public void deleterecord()
{
// if for any reason we are missing the reference
if (SelectedContactId == null) {
return;
}

// find the account record within the collection
Contact tobeDeleted = null;
for(Contact a : contactList)
if (a.Id == SelectedContactId) {
tobeDeleted = a;
break;
}
//if account record found delete it
if (tobeDeleted != null) {
delete tobeDeleted;
}

//refresh the data
LoadData();
}




}

Вопрос: Есть контроллер и  страница соответственно. Приведены ниже.  Почему не срабатывает отображение по выбранному количеству строк (5,10 и т.д.). То, что нету методов на "предыдущий следующий " это понятно и не суть. Оговорюсь сразу, что данный вариант нашел в интернете. Предполагаю, что не в том месте находиться ApexPages.StandardSetController. 

[code]
<apex:page Controller="ContactsManagerController">
    	<apex:form id="form" >
           
            <apex:pageBlock id="pbId">
           	<apex:actionFunction name="refreshPageSize" action="{!refreshPageSize}" status="fetchStatus" reRender="pbId"/>
                Search: &nbsp;
                <apex:inputText value="{!SearchContact}" label="Search"/>
                
                <apex:commandButton action="{!startSearch}" value="Search"/>
                &nbsp;
            	<apex:commandbutton action="{!URLFOR($Action.Contact.NewContact)}" value="New Contact"/>
     
                                
                <apex:pageBlockSection title="Contact information"  columns="1"  >
              	
                <apex:pageBlockTable value="{!contactList}" var="item" id="pbId">
                    
                    <apex:column >
                    <apex:outputLink title="" value="/{!item.id}/e?retURL=/apex/{!$CurrentPage.Name}" style="font-weight:bold">Edit</apex:outputLink>&nbsp;|&nbsp;
                    <a href="javascript:if (window.confirm('Are you sure?')) deleterecord('{!item.Id}');" style="font-weight:bold">Del</a>
                	
                    </apex:column>
                    
                    <apex:column headerValue="Name" >
                    <a href="/{item.Id}" target="_blank">{!item.Name}</a>
                    <apex:facet name="header">
        			<apex:commandLink action="{! getsortcontactsname }" 
            		reRender="pbId">Name
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    
                    <apex:column headerValue="Email" value="{!item.Email}">
                    <apex:facet name="header">
        			<apex:commandLink action="{! getsortcontactsEmail }" 
            		reRender="pbId">Email
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    
                    <apex:column headerValue="Contact Level" value="{!item.Contact_Level__c}">
                   
                    <apex:facet name="header">
        			<apex:commandLink action="{! getsortcontactsLevel }" 
            		reRender="pbId">Contact Level
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    
                  
                    <apex:column headerValue="Account" value="{!item.AccountId}">
                    <apex:facet name="header">
        			<apex:commandLink action="{! getsortaccount }" 
            		reRender="pbId">Account
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    
                    <apex:column headerValue="Owner" value="{!item.OwnerId}">
                    <apex:facet name="header">
        			<apex:commandLink action="{! getsortOwner }" 
            		reRender="pbId">Owner
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    
                    <apex:column headerValue="Created By" value="{!item.CreatedById}">
                    <apex:facet name="header">
        			<apex:commandLink action="{! getsortCreatedBy }" 
            		reRender="pbId">Created By
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    
                    <apex:column headerValue="Created Date" value="{!item.CreatedDate}">
                     <apex:facet name="header">
        			<apex:commandLink action="{! getsortCreatedDate }" 
            		reRender="pbId">Created Date
       				</apex:commandLink>
    				</apex:facet>
                    </apex:column>
                    

                    </apex:pageBlockTable>
                     
                                       
                    
                    <apex:panelGrid columns="8"> 
                 
                <apex:selectList value="{!size}" multiselect="false" size="1" onchange="refreshPageSize();">
                    <apex:selectOptions value="{!paginationSizeOptions}"/>
                </apex:selectList>
                        
                       
                 
                <apex:commandButton status="fetchStatus" reRender="pbId" value="First" action="{!setCon.first}" disabled="{!!setCon.hasPrevious}" title="First Page"/> 
  
                <apex:commandButton status="fetchStatus" reRender="pbId" value="Previous" action="{!setCon.previous}" disabled="{!!setCon.hasPrevious}" title="Previous Page"/> 
  
                <apex:commandButton status="fetchStatus" reRender="pbId" value="Next" action="{!setCon.next}" disabled="{!!setCon.hasNext}" title="Next Page"/> 
  
                <apex:commandButton status="fetchStatus" reRender="pbId" value="Last" action="{!setCon.last}" disabled="{!!setCon.hasNext}" title="Last Page"/> 
  
                <apex:outputText >{!(setCon.pageNumber * size)+1-size}-{!IF((setCon.pageNumber * size)>noOfRecords, noOfRecords,
                     (setCon.pageNumber * size))} of {!noOfRecords}
                </apex:outputText> 
                
                         <apex:outputPanel >                      
                    <apex:actionStatus id="fetchStatus" >
                        <apex:facet name="start" >
                          <img src="/img/loading.gif" />                    
                        </apex:facet>
                    </apex:actionStatus>
                </apex:outputPanel>      
               
  
            </apex:panelGrid>  
               
              </apex:pageBlockSection>
                <apex:actionFunction action="{!deleterecord}" name="deleterecord" reRender="form" >
            <apex:param name="contacts" value="" assignTo="{!SelectedContactId}" />
        </apex:actionFunction>
               
    		</apex:pageBlock>
     </apex:form>
</apex:page>


[/code]



[code]

public with sharing  class ContactsManagerController {
     
    public List<Contact> contactList {get;set;}
    public String SearchContact {get; set;}
    Public Integer size{get;set;} 
    Public Integer noOfRecords{get; set;} 
    
    public string SelectedContactId { get; set; }
    
    public List<SelectOption> paginationSizeOptions{get;set;}
    
    public ContactsManagerController () {
    
          size=10;
        paginationSizeOptions = new List<SelectOption>();
        paginationSizeOptions.add(new SelectOption('5','5'));
        paginationSizeOptions.add(new SelectOption('10','10'));
        paginationSizeOptions.add(new SelectOption('20','20'));
        paginationSizeOptions.add(new SelectOption('50','50'));
        paginationSizeOptions.add(new SelectOption('100','100'));  
      
	SearchContact  = '';
    
	
	String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c,'
 							 + 'Account.Name, Owner.Name, CreatedBy.Name,'
     							+ ' CreatedDate FROM Contact';
                    	
   	this.contactList = Database.query(contactqauery); 
        
	
    LoadData();
    
    } 
    
        public  ApexPages.StandardSetController setCon {
      		
            get {
            if(setCon == null) {                
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                      [select Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact]));
                setCon.setPageSize(size);  
                noOfRecords = setCon.getResultSize();
            }            
            return setCon;
        }
        set;
    }
    
    // Initialize setCon and return a list of record    
     
    public List<Contact> getcontact() {																			
        
         return (List<Contact>) setCon.getRecords();
    }
    
    
         //Changes the size of pagination
    public  PageReference refreshPageSize() {
         setCon.setPageSize(size);
         return NULL;
    }
    
    
    
    
   
    
   
    
    public void startSearch () {
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c,'
       					   +'Account.Name, Owner.Name, CreatedBy.Name,' 
     					 	+' CreatedDate FROM Contact '
        					+' WHERE LastName =:SearchContact OR FirstName =:SearchContact';    
    this.contactList = Database.query(contactqauery); 
    
	}
	

    
    public void getsortcontactsname () {
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact  ORDER BY Name ASC';    
    this.contactList = Database.query(contactqauery);
    } 

    public void getsortcontactsEmail (){
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact  ORDER BY Email ASC';
    this.contactList = Database.query(contactqauery);    
    }
    
    public void getsortcontactsLevel (){
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact  ORDER BY Email ASC';
    this.contactList = Database.query(contactqauery);
    }
    
    public void getsortaccount (){
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact  ORDER BY Account.Name ASC';
    this.contactList = Database.query(contactqauery);      
    }
    
    public void getsortOwner () {
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact  ORDER BY Owner.Name ASC';
    this.contactList = Database.query(contactqauery);      
    }
        
    public void getsortCreatedBy (){
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact  ORDER BY CreatedBy.Name ASC';
    this.contactList = Database.query(contactqauery);      
    }        
        
    
    public void getsortCreatedDate () {
    String contactqauery = 'SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact   WHERE CreatedDate < TODAY';
    this.contactList = Database.query(contactqauery);      
    }   
  
   
	private void LoadData() {
		contactList = [SELECT Id, Name, Email, Contact_Level__c, Account.Name, Owner.Name, CreatedBy.Name, CreatedDate FROM Contact LIMIT 10000];
	}
 
	public void deleterecord()
		{
			// if for any reason we are missing the reference
			if (SelectedContactId == null) {
				return;
			}
 
			// find the account record within the collection
			Contact tobeDeleted = null;
			for(Contact a : contactList)
				if (a.Id == SelectedContactId) {
					tobeDeleted = a;
					break;
				}
			//if account record found delete it
			if (tobeDeleted != null) {
				delete tobeDeleted;
			}
 
			//refresh the data
			LoadData();
		}
    
    
    
    
}




[/code]
https://paste.ofcode.org/QpHd7GhF4SQg7bAPrhpJsu - controller
https://paste.ofcode.org/3an8eJiqm8rN9n7N7Dj5KwM  - страница

Maxim Elets
https://paste.ofcode.org/QpHd7GhF4SQg7bAPrhpJsu - controller
https://paste.ofcode.org/3an8eJiqm8rN9n7N7Dj5KwM - страница

Ты как всегда был прав!

[quote="Maxim Elets"]https://paste.ofcode.org/QpHd7GhF4SQg7bAPrhpJsu - controller
https://paste.ofcode.org/3an8eJiqm8rN9n7N7Dj5KwM  - страница[/quote]

Ты как всегда был прав!