I have an issue here with the checkbox checked.
I've read a lot of solution, but they always say add the 'values' => array('something')
I've followed that solution but nothing change. I've deploy again, but no use. The checkbox still not checked.
I've added the "checked" => true. But doesn't work too.
Here is my code and debug as well.
$this->addColumn(
 'in_banner',
 [
 'type' => 'checkbox',
 'name' => 'in_banner',
 'values' => $this->_getSelectedSlide(),
 'index' => 'id',
 'checked' => true,
 'header_css_class' => 'col-select col-massaction',
 'column_css_class' => 'col-select col-massaction'
 ]
 );
As you can see, i set 'values' => $this->_getSelectedSlide(), so i'll bebug that function so you guys can see its an array like what they told me to.
enter image description here 
Also, when i click on checked, it not render checked = "checked".
enter image description here 
EDIT 1:
I'm follow @kunj solution, but i dont think that's gonna work, because i'm doing after catalog_category_product and this is what i debug in they code. Its really dont have any difference.
enter image description here 
So, i've try this but doesn't work, also i've run command di:compile, staic-content:deploy, setup:upgrade
$this->addColumn(
 'in_banner',
 [
 'type' => 'checkbox',
 'name' => 'in_banner',
 'values' => [1,2],
 'index' => 'id',
 'checked' => true,
 'header_css_class' => 'col-select col-massaction',
 'column_css_class' => 'col-select col-massaction'
 ]
 );
EDIT 2:
Here is my code:
C:\xampp\htdocs\magento\app\code\Aht\BannerSlider\Block\Adminhtml\Banner\Tab\Slide.php
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
/**
 * Slide in banner grid
 *
 * @author Magento Core Team <[email protected]>
 */
namespace Aht\BannerSlider\Block\Adminhtml\Banner\Tab;
use Magento\Backend\Block\Widget\Grid;
use Magento\Backend\Block\Widget\Grid\Column;
use Magento\Backend\Block\Widget\Grid\Extended;
class Slide extends \Magento\Backend\Block\Widget\Grid\Extended
{
 /**
 * Core registry
 *
 * @var \Magento\Framework\Registry
 */
 protected $_coreRegistry = null;
 /**
 * @var \Aht\BannerSlider\Model\SlideFactory
 */
 protected $_slideFactory;
 protected $_bannerSlideFactory;
 public function __construct(
 \Magento\Backend\Block\Template\Context $context,
 \Magento\Backend\Helper\Data $backendHelper,
 \Aht\BannerSlider\Model\SlideFactory $slideFactory,
 \Aht\BannerSlider\Model\BannerSlideFactory $bannerSlideFactory,
 \Magento\Framework\Registry $coreRegistry,
 array $data = []
 ) {
 $this->_slideFactory = $slideFactory;
 $this->_bannerSlideFactory = $bannerSlideFactory;
 $this->_coreRegistry = $coreRegistry;
 parent::__construct($context, $backendHelper, $data);
 }
 /**
 * @return void
 */
 protected function _construct()
 {
 parent::_construct();
 $this->setId('banner_slider_banner_slide');
 $this->setDefaultSort('id');
 $this->setUseAjax(true);
 }
 /**
 * @return array|null
 */
 public function getBanner()
 {
 return $this->_coreRegistry->registry('banner');
 }
 /**
 * @param Column $column
 * @return $this
 */
 protected function _addColumnFilterToCollection($column)
 {
 $field = $column->getFilterIndex() ? $column->getFilterIndex() : $column->getIndex();
 if ($column->getId() == 'in_banner') {
 $slideIds = $this->_getSelectedSlide();
 if (empty($slideIds)) {
 $slideIds = 0;
 }
 if ($column->getFilter()->getValue()) {
 $this->getCollection()->addFieldToFilter('id', ['in' => $slideIds]);
 } elseif (!empty($slideIds)) {
 $this->getCollection()->addFieldToFilter('id', ['nin' => $slideIds]);
 }
 } else {
 parent::_addColumnFilterToCollection($column);
 }
 return $this;
 }
 /**
 * @return Grid
 */
 protected function _prepareCollection()
 {
 $collection = $this->_slideFactory->create()->getCollection();
// ->addFieldToSelect(array('id', 'name', 'image'));
// check id vì 2 TH , add và update
 if ($this->getRequest()->getParam('id')) {
 $this->setDefaultFilter(['in_banner' => 1]);
// main_table được lấy tự động.
 $collection->getSelect()
 ->joinInner(['banner_slide' => 'banner_slide'], 'main_table.id = banner_slide.slide_id')
 ->where('banner_id = ?', $this->getBanner()->getId());
// phải để addFilterToMap ở bên ngoài thì mới chạy được filter by created_at.
// nó thay created_at = main_table.created_at
 $collection->addFilterToMap('created_at', 'main_table.created_at');
 $collection->addFilterToMap('updated_at', 'main_table.updated_at');
 $collection->addFilterToMap('id', 'main_table.id');
// hiển thị câu lệnh sql:
// echo $collection->getSelect();die();
 } else {
 $collection->addFieldToSelect('*')->load();
 $collection->getItems();
 $collection->addFilterToMap('created_at', 'main_table.created_at');
 $collection->addFilterToMap('updated_at', 'main_table.updated_at');
 }
 $this->setCollection($collection);
 return parent::_prepareCollection();
 }
 /**
 * @return Extended
 */
 protected function _prepareColumns()
 {
 $this->addColumn(
 'in_banner',
 [
 'type' => 'checkbox',
 'name' => 'in_banner',
// 'values' => $this->_getSelectedSlide(),
 'values' => ['1,2'],
 'index' => 'id',
 'header_css_class' => 'col-select col-massaction',
 'column_css_class' => 'col-select col-massaction'
 ]
 );
 $this->addColumn(
 'id',
 [
 'header' => __('ID'),
 'sortable' => true,
 'index' => 'id',
 'header_css_class' => 'col-id',
 'column_css_class' => 'col-id'
 ]
 );
 $this->addColumn('name', ['header' => __('Name'), 'index' => 'name']);
 $this->addColumn('url', ['header' => __('URL'), 'index' => 'url']);
 $this->addColumn('image', ['header' => __('Image'), 'index' => 'image']);
 $this->addColumn(
 'position',
 [
 'header' => __('Position'),
 'type' => 'number',
 'index' => 'position',
 ]
 );
 $this->addColumn(
 'created_at',
 [
 'header' => __('Created Time'),
 'type' => 'datetime',
 'index' => 'created_at'
 ]
 );
 $this->addColumn(
 'updated_at',
 [
 'header' => __('Last Update'),
 'type' => 'datetime',
 'index' => 'updated_at'
 ]
 );
 $this->addColumn(
 'action',
 [
 'header' => __('Remove'),
 'type' => 'action',
 'getter' => 'getId',
 'actions' => [
 [
 'caption' => __('Remove'),
 'url' => [
 'base' => 'banner/slide/remove'
 ],
 'confirm' => 'Are you sure?',
 'field' => 'id'
 ]
 ],
 'filter' => false,
 'sortable' => false,
 'index' => 'stores',
 'header_css_class' => 'col-action',
 'column_css_class' => 'col-action'
 ]
 );
 return parent::_prepareColumns();
 }
 /**
 * @return string
 */
 public function getGridUrl()
 {
 return $this->getUrl('banner/*/grid', ['_current' => true]);
 }
 /**
 * @return array
 */
 protected function _getSelectedSlide()
 {
 // get slide position trong bảng banner_slide
 $slide = $this->getRequest()->getPost('selected_slide');
 if ($slide === null) {
 $slide = $this->getBanner()->getSlidePosition();
 return array_keys($slide);
 }
 return $slide;
 }
}
Its works wonderful, except the checkbox doesn't checked, and also, cant search with ID, but still can search with others (ex: name, image, url, created_at, updated_at).
In case you need more code:
Here is my template
C:\xampp\htdocs\magento\app\code\Aht\BannerSlider\view\adminhtml\templates\banner_slide\banner\edit\assign_slide.phtml
<?php
/** @var \Aht\BannerSlider\Block\Adminhtml\Banner\AssignSlide $block */
/** @var \Aht\BannerSlider\Block\Adminhtml\Banner\Tab\Slide $blockGrid */
$blockGrid = $block->getBlockGrid();
$gridJsObjectName = $blockGrid->getJsObjectName();
?>
<?= $block->getGridHtml() ?>
<input type="hidden" name="banner_slide" id="in_banner_slide" data-form-part="banner_form" value="" />
<script>
 require([
 'assign_slide'
], function (assign_slide) {
 assign_slide.assignSlide({
 "selectedSlide": <?= /* @escapeNotVerified */ $block->getSlideJson() ?>,
 "gridJsObjectName": <?= /* @escapeNotVerified */ '"' . $gridJsObjectName . '"' ?: '{}' ?>
 });
});
</script>
<!-- @todo remove when "UI components" will support such initialization -->
<script>
 require('mage/apply/main').apply();
</script>
The template call to a js file, but that doesn't matter with my problem right now, i thing, because when i remove this code in js file in pub/static , it still not checked in the checkbox.
C:\xampp\htdocs\magento\app\code\Aht\BannerSlider\Block\Adminhtml\Banner\AssignSlide.php
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aht\BannerSlider\Block\Adminhtml\Banner;
//use Aht\BannerSlider\Block\Adminhtml\Banner\Tab\Slide;
class AssignSlide extends \Magento\Backend\Block\Template
{
 /**
 * Block template
 *
 * @var string
 */
 protected $_template = 'banner_slide/banner/edit/assign_slide.phtml';
 /**
 * @var \Aht\BannerSlider\Block\Adminhtml\Banner\Tab\Slide
 */
 protected $blockGrid;
 /**
 * @var \Magento\Framework\Registry
 */
 protected $registry;
 protected $_bannerSlideFactory;
 /**
 * @var \Magento\Framework\Json\EncoderInterface
 */
 protected $jsonEncoder;
 public function __construct(
 \Magento\Backend\Block\Template\Context $context,
 \Magento\Framework\Registry $registry,
 \Magento\Framework\Json\EncoderInterface $jsonEncoder,
 \Aht\BannerSlider\Model\BannerSlideFactory $bannerSlideFactory,
// Slide $blockGrid,
 array $data = []
 ) {
 $this->registry = $registry;
 $this->jsonEncoder = $jsonEncoder;
 $this->_bannerSlideFactory = $bannerSlideFactory;
// $this->blockGrid = $blockGrid;
 parent::__construct($context, $data);
 }
 /**
 * Retrieve instance of grid block
 *
 * @return \Magento\Framework\View\Element\BlockInterface
 * @throws \Magento\Framework\Exception\LocalizedException
 */
 public function getBlockGrid()
 {
 if (null === $this->blockGrid) {
 $this->blockGrid = $this->getLayout()->createBlock(
 \Aht\BannerSlider\Block\Adminhtml\Banner\Tab\Slide::class,
 'banner.slide.grid'
 );
 }
 return $this->blockGrid;
 }
 /**
 * Return HTML of grid block
 *
 * @return string
 */
 public function getGridHtml()
 {
 return $this->getBlockGrid()->toHtml();
 }
 /**
 * @return string
 */
 public function getSlideJson()
 {
 $slide = $this->getBanner()->getSlidePosition();
 if (!empty($slide)) {
 return $this->jsonEncoder->encode($slide);
 }
 return '{}';
 }
 /**
 * Retrieve current category instance
 *
 * @return array|null
 */
 public function getBanner()
 {
 return $this->registry->registry('banner');
 }
}
This AssignSlide.php file call the template out, which is assign_slide.phtml.
2 Answers 2
So, after some help, i've found the answer.
 I trace after addColumn() function and realize it run into Checkbox.php
C:\xampp\htdocs\magento\vendor\magento\module-backend\Block\Widget\Grid\Column\Renderer\Checkbox.php
So i debugged in that checkbox.php and one again, i realize that my problem wasn't in the 'values' => [1,2] or something, because the checkbox.php have this code :
public function render(\Magento\Framework\DataObject $row)
{
 $values = $this->_getValues();
 $value = $row->getData($this->getColumn()->getIndex());
 $checked = '';
 if (is_array($values)) {
 $checked = in_array($value, $values) ? ' checked="checked"' : '';
 } else {
 $checkedValue = $this->getColumn()->getValue();
 if ($checkedValue !== null) {
 $checked = $value === $checkedValue ? ' checked="checked"' : '';
 }
 }
 $disabled = '';
 $disabledValues = $this->getColumn()->getDisabledValues();
 if (is_array($disabledValues)) {
 $disabled = in_array($value, $disabledValues) ? ' disabled="disabled"' : '';
 } else {
 $disabledValue = $this->getColumn()->getDisabledValue();
 if ($disabledValue !== null) {
 $disabled = $value === $disabledValue ? ' disabled="disabled"' : '';
 }
 }
 $this->setDisabled($disabled);
 if ($this->getNoObjectId() || $this->getColumn()->getUseIndex()) {
 $v = $value;
 } else {
 $v = $row->getId() != "" ? $row->getId() : $value;
 }
 return $this->_getCheckboxHtml($v, $checked);
}
As you can see, the $values = $this->_getValues(); is return my array, which is pass through 'values' => [1,2] stuff, and $value = $row->getData($this->getColumn()->getIndex()); is pass through this code:
$this->addColumn(
 'in_banner',
 [
 'type' => 'checkbox',
 'name' => 'in_banner',
 'values' => $this->_getSelectedSlide(),
 'index' => 'slide_id',
 'header_css_class' => 'col-select col-massaction',
 'column_css_class' => 'col-select col-massaction'
 ]
 );
Which mean $values = [1,2] and $value = 1, After that, it compare $value with $values and see if $value is inside $values or not, which mean 1 is inside array(1,2) or not. If it do inside, then "checked = checked" , else ..
So the point is what i've done wrong here is i has tranfer id of the banner_slide table, when it should be slide_id in banner_slide table.
enter image description here 
And why am i do after catalog_category_product but my code doesn't work, its because i heard they use something called entity, EAV. Right now, i dont understand much about that, but i will find it out soon.
Thanks you all for reading and helping me :)
$this->addColumn( 'banner', [ 'type' => 'checkbox', 'name' => 'in_banner', 'values' => $this->_getSelectedSlide(), 'index' => 'id', 'checked' => true, 'header_css_class' => 'col-select col-massaction', 'column_css_class' => 'col-select col-massaction' ] );
following code use to set checkbox on grid and 'values' is use to get and by defult chekbox set selected in this code _getSelectedSlide() is use to send selected ids array pass to render() function.
so which checkbox you set selected this checkbox ids set in array and pass in 'values '
public function _getSelectedSlide(){ return array([0] => 20 [1]=>23 [2] => 32); }
'values' => [1,2,3],must work you can refer from magentoMagento\User\Block\Role\Grid\User.