i am new to cakephp .. i am implementing a Timezone feature in my webapp i am using this timezone helper class in order to show time in my select box
http://bakery.cakephp.org/articles/MarkAlanEvans/2009/12/17/updated-timezone-helper
in my view i am echoing timezone in select box like this
echo $this->Timezone->select('timezone');
what i am doing right now is i am taking the value of whatever the time user has selected and then update the field of timezone in database ... what i want now is when the user wants to again change the timezone how he can see his old timezone in selectbox as a default value .. the first thing i dont know how can i add the default value to my selectbox
my helper class has this function
function select($fieldname, $label="Please Choose a timezone") {
$list = $this->Form->input($fieldname, array("type"=>"select", "label"=>$label, "options"=>$this->timezones, "error"=>"Please choose a timezone"));
return $this->output($list);
}
2nd thing is this as if i want to show the default value, obviously i have to query from the database and then retreive the old timezone of the user.. so the problem is if i have to attach the default value to my helper class for example like this
$list = $this->Form->input($fieldname, array("type"=>"select",'default'=>'$oldtimezone', "label"=>$label, "options"=>$this->timezones, "error"=>"Please choose a timezone"));
return $this->output($list);
so in order to do should i have to loadmodel in helper class and then query in helper class? is that possible ? or is that i am not going against cakephp or mvc rules ? so then my next question becomes how can i load the modal inside helper.
because if i can be able to add default value to here like this
echo $this->Timezone->select('timezone',array('default'=>'oldtimezone'));
then i think there is no need for me to make changes in the helper class as i simple pass variable from controller to this view
The proper way to pass default values to the view is to do that in the else block of the controller:
if (posted) {
//validate and save
} else {
//default values here
$this->request->data['Modelname']['timezone'] = $timeZoneFromDb;
}
This way you leverage the controllers logic and you dont have to do anything in the view/helper.
See http://www.dereuromark.de/2010/06/23/working-with-forms/ for details (default value section).
Related
I want to accomplish a NOT IN clause in CakePHP, but I am not able to achieve it. I've been reading the CakePHP Cookbook and some answers here in StackOverflow but it's not working for me.
I have a Table named 'Hotel' with all its model, controller and views. In the view template I built a CakePHP Cell where I want to show other Hotels, except for the hotel that is currently being viewed. If for example, I am showing the view of a hotel with id #5, I want to show other hotels options, except for that hotel view id number.
I have the following query in the Cell Controller:
$hotels = $this->Hotels->find('all')
->where(['Hotels.id NOT IN' => $current_hotel_id])
->limit(4)
->order('rand()')
->toArray();
I want $current_hotel_id to have the value of current hotel that it's being viewed. That's the approach I am taking.
Any useful information would be appreciated.
If you need some value that is available in your controller in cell, you must pass that value to it.
First, declare an argument in cell action:
class HotelsCell extends Cell{
public function hotels($current_hotel_id){
//your code here
}
}
Then, in your view, pass argument to cell:
$this->cell("Hotels::hotels",[$hotel->id])
More info in docs: Passing Arguments to a Cell
The fact that ng-change is only for user input, and does not fire when changes are made to the model programmatically, is really causing me a headache today. I'm working with a user input form which has the separate parts of a name, as well as dynamically built and ordered credentials. The form has a "displayName" field that gets updated when the name parts are changed. This is encapsulated in a directive which I need to use in a larger view. Here's where things get hairy. I need to hide the name part fields in my directive and use the outer form's name fields. I thought this would be easy by wiring up a function to update the hidden text input fields, and thus my displayName field. Then I found out programmatic changes to the model do not fire the change event.
I tried creating a watch for one of the name fields to see if I could get it to update the displayName field, but no luck.
this.scope.$watch('provider.firstName', function (event) {
namePropertyChanged2(displayNameOverridden, displayName, provider, credentials);
});
When I change the input field for firstName, it modifies the directive's value 'provider.firstName', and runs the 'namePropertyChanged2' function. The code listed runs in an initialize function, where 'displayName' is a local variable assigned from this.scope.provider.displayName. The watch assignment required me to make local variables instead of passing in controller variables. Not sure why, but whatever. So this function runs and 'displayName' is updated with the correct value... and the input field it's bound to is not updated. Bummer.
What would be ideal is to manually trigger the change event when the model changes, which would update the displayName and much rejoicing to be had.
Using CakePHP 2.6.7
I have created a plugin and there are 2 variables which for the most part are effectively constants - but the user should be able to change their values (they are paths to header and footer images).
I had been trying to use Configure::read() and Configure::write() but now realise that isn't what Configure is intended for and doesn't actually work in that manner at all.
How should these two variables be stored so that the values can be changed by a user and these changes would be permanent (until they make another change)?
Initial Solution
I've now solved the problem by serializing the data in an array to a text file. It would be great if someone had a more elegant solution though.
Simplest solution would be to store these values in the database as settings and then load them in.
We often do this using a Setting model to store the name-value pairs then attach a component (often to AppController) that loads in the data. For example, create a component like this:-
App::uses('Component', 'Controller');
class SettingsComponent extends Component {
public function initialize(Controller $Controller) {
$Controller->loadModel('Setting');
$settings = $Controller->Setting->find('all');
foreach($settings as $setting) {
Configure::write('Setting.' . $setting['Setting']['name'], $setting['Setting']['value']);
}
return;
}
}
Then load this for any controller that needs these settings:-
public $components = array('Settings');
You can then access the values in your code like:-
Configure::read('Setting.app_name', 'My Cake App');
You can easily extend the functionality of the component and what is stored in the settings table to make this approach as flexible as you need.
I have a Grid panel containing records which, on-click, will be loaded into a Form panel for editing.
On "close" of our form panel, we're calling myForm.getForm.reset(), which seems to reset the record but the values in the form fields themselves persist.
// Load record
me.down('form').loadRecord(record);
// Close
me.down('form').getForm().reset() or me.down('form').reset()
Please advise how to also clear values in the form upon resetting our record.
Do you have trackResetOnLoad set to true for the form? If so, what you really want is it set to false.
Maybe you need set 'resetRecord' parameter into 'reset()' method for unbind any record set by 'loadRecord' method.
Example:
me.down('form').getForm().reset(true)
You can override the default form panel to add this functionality. Add the following to your code:
Ext.override(Ext.form.Panel, {
clearForm:function(){
Ext.each(this.getForm().getFields().items, function(field){
field.setValue('');
});
}
});
You can then clear a form using:
myForm.clearForm()
Where myForm is your form panel.
The reset() method just resets the form back to the last record loaded.
If you want to maintain trackResetOnLoad=true (e.g. so you can use the form's "dirtychange" event) another approach is to take a copy of the values just after the form is created like var originalValues = myForm.getFieldValues(); then simply restore those values using myForm.setValues(originalValues); instead of calling myForm.reset(...);
You can try this...
this.up('form').getForm().reset();
I have a model called PageMetaData that contains a title and a description. This is to be tied to any other model and to be used as the title tag and meta description for the page.
So I have a model called Brand. Brand has a field called page_meta_data_id and Brand belongsTo PageMetaData
Now on the view for Brand I can run this code:
if(!empty($data['PageMetaData']['title']))
{
$this->set('title_for_layout', $data['PageMetaData']['title']);
}
else if(!empty($data['Brand']['name']))
{
$this->set('title_for_layout', $data['Brand']['name']);
}
if(!empty($data['PageMetaData']['description']))
{
echo $this->Html->meta('description', $data['PageMetaData']['description'],array('inline'=>false));
}
else if(!empty($data['Brand']['description']))
{
echo $this->Html->meta('description', $data['Brand']['description'],array('inline'=>false));
}
And if a PageMetaData has been associated to the current Brand and has a value for title, it will set that as the page title, otherwise if the brand has a field called name it will us that. Same for description.
The problem is I don't want to have to diplicate this code in every view for every model that uses PageMetaData.
I cannot figure out where I can abstract the code to, to avoid duplication.
I cannot put it in a Behavior or a Helper because you cannot set the title from either. I cannot put it in a Component because it cannot access the data found from the model.
Is there somewhere I can put this code for reuse?
You can possibly use elements for this. have a look at the cookbook link:
http://book.cakephp.org/view/1081/Elements
Place the method in your AppModel. I assume the method accepts an id for it to return the appropriate data.
Place another method in your AppController's beforeRender method. Pass the id to this method; which in turn will call the method in AppModel; setting title_for_layout, meta_description and keywords.
You should also not echo out these values, but rather pass them to the view and output them there (or in the layout).
AppController and AppModels are application-wide; so any controller/model may access the methods.
I'm sure there's other methods; and this might not work as I haven't tested it.