List with Views published nodes in the form of a table. Add to a table with a column that will contain a link. By clicking on the link ajax request should be sent, which makes the node unpublished.
I have views, have a link, have alert-ajax. But I don't understand how I can change the status from 0 to 1 programmatically.
My code in controller -
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\RemoveCommand;
use Drupal\Core\Controller\ControllerBase;
class CustomAjaxLinkController extends ControllerBase{
public function customAjaxLinkAlert($node) {
$query = \Drupal::entityQuery('node');
$query->condition('status', 1);
$node = $query->execute();
$status = $node-> isPublished();
if ($status === TRUE) {
$node->status = 0;
$node->save();
}
$response = new AjaxResponse();
$selector = '.customAjaxLinkAlert' ;
$response->addCommand(new RemoveCommand($selector, $node));
return $response;
}
}
There is an error in it, but I cannot figure out what I am doing wrong
You can past data's via ajax in a Drupal Controller
$.ajax({
type: 'POST',
url: '/your_module/your_function',
data: {'data': data},
});
Then in your Controller
<?php
namespace Drupal\your_module\your_contoller;
use Drupal\Core\Controller\ControllerBase;
/**
* Class your_contoller.
*/
class your_contoller extends ControllerBase {
public function your_function() {
do what you want
}
}
OR
Your button is inside a form and will submit the value.
Related
I successfully created a custom admin module and loaded successfully in the menu and rendered phtml file successfully.
Then i tried to load some dummy data via ajax using angularJS in same admin module when clicking a button, but the ajax call returns the html content of dashboard of magento admin.
I followed this link
Following is the code for controller
<?php
namespace DVendor\DemoModule\Controller\Adminhtml\DemoPart;
use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\Controller\Result\JsonFactory;
class Index extends \Magento\Backend\App\Action
{
/**
* #var \Magento\Framework\View\Result\PageFactory
*/
protected $resultPageFactory;
protected $jsonPageFactory;
public function __construct(Context $context,PageFactory $resultPageFactory,JsonFactory $jsonPageFactory){
$this->resultPageFactory = $resultPageFactory;
$this->jsonPageFactory = $jsonPageFactory;
parent::__construct($context);
}
public function execute()
{
if($this->getRequest()->isAjax()){
$result = $this->jsonPageFactory->create();
$test=array(
'Firstname' => 'What is your firstname',
'Email' => 'What is your emailId',
'Lastname' => 'What is your lastname',
'Country' => 'Your Country'
);
return $result->setData($test);
}
else{
return $resultPage = $this->resultPageFactory->create();
}
}
}
?>
Following is the JS Code used in phtml file
$http({
method:'POST',
url:'<?php echo $this->getUrl('demomodule/demopart'); ?>',
//data:$.param({'limit':$scope.definedlimits.value}),
headers:{'Content-Type':'application/x-www-form-urlencoded'}
}).then(function(response) {
var data = response.data;
console.log(data);
},function(response){
console.log(response.data);
});
I'm trying to send a simple AJAX request from my view, and I'm using cakePHP's JSON view to do so, but I'm unable to get _serialize to prevent the controller from seeking a ctp file--I consistently get a "Status 500: view file ... is missing" error. I've read the docs and several similar questions on stackoverflow, and I can't see what I'm missing.
I've added the requesthandler to my initialize function in AppController:
public function initialize() {
$this->loadComponent('RequestHandler');
}
enabled extensions:
Router::parseExtensions('json');
require CAKE . 'Config' . DS . 'routes.php';
I've added the component to my controller:
class StudentsController extends AppController {
public $name = 'Students';
public $components = array('RequestHandler');
The only thing that seems to change it is when I add the following code to AppController's beforeFilter method--just renders the word "null":
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
$this->set('_serialize', true);
This is my controller method:
public function set_rating() {
$this->autoLayout = false;
$this->autoRender = false;
$this->response->type('application/json');
$studentID = (int) $this->request->data['studentID'];
$rating = (int) $this->request->data['rating'];
$this->Student->id = $studentID;
if($this->Student->saveField('rating', $rating)) {
$this->set('success', 1);
}
else{
$this->set('success', 0);
}
$this->set("_serialize", array("success"));
}
and the Ajax request:
$.ajax({
url: '<?php echo $this->webroot . $this->params["controller"]; ?>/set_rating.json',
type: "POST",
dataType: "json",
data: {studentID: text, rating: value},
success: function(response) {
if(response['success'] == 1){
manageFlashMessage('alert-success', 'Rating saved.');
}
else {
manageFlashMessage('alert-danger', 'Sorry, something went wrong');
}
},
error: function (xhr, status, error) {
console.log(xhr.status);
console.log(xhr.responseText);
console.log(status);
}
});
I can't see what I'm missing! Any ideas?
I had the same error message in a similar context; In my case, it was due to the fact that the method I was trying to call didn't get through the isAuthorized function. As such, it was redirected to another method, which was not intended to be viewed in json format, and that's how the "Status 500: view file ... is missing" error message came about.
I simply had to add the appropriate exception for my json method within the isAuthorized function and that fixed it.
To debug these types of errors, one can try to access the url directly instead through an ajax call, because then the corresponding permission error message will be shown.
I've a question : when a validation request FAILED on an UPDATE form, how can I show the posted data, on which errors occurs ?
In this exemple, it justs shows the data fetched from the DB (not the "old", previouly modified) :
// ****************
// Controller
// ****************
public function update(Article $article)
{
return view('article.update',compact('article'));
}
public function handleupdate(Requests\UpdateArticleRequest $request)
{
$article = Article::findOrFail(Request::input('id'));
$article->fill($request->all());
$article->save();
return Redirect::to('/');
}
// ****************
// ValidationRequest
// ****************
class UpdatearticleRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required | min:3',
'description' => 'required | max:255
];
}
}
I've seen the Request::old and Request::flash() but I don't understant how to "glue" all these things together.
Thanks in advance for your help.
Paguemaou
If you are using Laravel Form (eg Form::text, Form::select) then these will be filled automatically from the value in the session.
See https://laracasts.com/discuss/channels/general-discussion/laravel-5-forms for more info as Form-s are not installed by default in Laravel 5 anymore.
In CakePHP 2.1 I'm trying to test that the CakeEmail::to() method is called from my model test case with the correct "to" email (In this example: cat#gmail.com).
I want the following test to pass but I get:
Expectation failed for method name is equal to <string:to> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
Here's the code in the Model and the test case:
<?php
// Model/Job.php
App::uses('AppModel', 'Model');
App::uses('CakeEmail', 'Network/Email');
class Job extends AppModel {
public function emailCat() {
$CakeEmail = new CakeEmail();
$CakeEmail->to('cat#gmail.com');
$CakeEmail->subject('hello!');
$CakeEmail->emailFormat('text');
$CakeEmail->config('default');
$CakeEmail->send('hi');
}
}
// Test/Model/JobTest.php
class JobTestCase extends CakeTestCase {
public function setUp() {
parent::setUp();
$this->Job = ClassRegistry::init('Job');
}
public function testEmailCat() {
// I want to assert CakeEmail::to() is called with correct email
$CakeEmail = $this->getMock('CakeEmail' , array('to'));
$CakeEmail->expects($this->once())
->method('to')
->with($this->equalTo('cat#gmail.com'));
$result = $this->Job->emailCat();
}
}
The problem is that you're mocking a completely different class then the one that is actually used on the model. On your model function, you instantiate a brand new email class which will be mocked. Instead, you need to make sure that the CakeEmail object that the model uses is the one mocked.
class Job extends AppModel {
public $CakeEmail = null;
public function emailCat() {
if (!$CakeEmail) {
$this->CakeEmail = new CakeEmail();
}
$this->CakeEmail = new CakeEmail();
$this->CakeEmail->to('cat#gmail.com');
$this->CakeEmail->subject('hello!');
$this->CakeEmail->emailFormat('text');
$this->CakeEmail->config('default');
$this->CakeEmail->send('hi');
}
}
Then update your test case to set the mock object on your Job model.
class JobTestCase extends CakeTestCase {
public function setUp() {
parent::setUp();
$this->Job = ClassRegistry::init('Job');
}
public function testEmailCat() {
// I want to assert CakeEmail::to() is called with correct email
$CakeEmail = $this->getMock('CakeEmail' , array('to'));
$CakeEmail->expects($this->once())
->method('to')
->with($this->equalTo('cat#gmail.com'));
// use mock object instead of creating a brand new one
$this->Job->CakeEmail = $CakeEmail;
$result = $this->Job->emailCat();
}
}
I'm trying to log every write operation so I'm using the afterSave and afterDelete callbacks in AppModel. Basically I need to log(for the moment): the model , the controller function, the loggedin user data and the remote ip
It seems that I was able to get all of them but I don't know how to get the controller function name.
This is the aftersave function I have now:
public function afterSave($created) {
App::uses('Folder', 'Utility');
$month = date("y-m");
if(!is_dir('../tmp/logs/'.$month)) {
$dir = new Folder('../tmp/logs/'.$month, true);
}
App::uses('CakeSession', 'Model/Datasource');
$user_id = CakeSession::read('Auth.User.username');
if($created) {
$id = 'New';
} else {
$id = $this->data[$this->alias]['id'];
}
$str = 'WRITE Action. Model: '.$this->alias.'. Controller: functon_name. ID:'.$id.'. Username: '.$user_id.'. Client IP: '.$this->getIP();
CakeLog::write($month.'/'.date("d-m-y"), $str);
}
Thanks
You're doing this on the model, which has no knowledge of the controller (and really shouldn't). I'd suggest copying the CakeRequest object to the model so you have that information. Here's one way:
//controller
function beforeFilter() {
$this->{$this->modelClass}->request = $this->request;
}
Then you can access the request object from the model. Use $this->request['params']['action'] to get the current dispatched action.
It's worth suggesting that you might want to move this to the read() method on a custom datasource, as afterSave() can possibly be skipped and therefore not logged.