18

BaseElementModel::getContent() will return the element’s ContentModel. It has two purposes: To store the element’s data from the craft_content table table when fetching elements from the DB. To store the POST data that should be stored in the craft_content table when saving an element to the DB. In both cases, the ContentModel should not actually be ...


14

Yep, you can do that with Craft.createElementSelectorModal(): var myModal = Craft.createElementSelectorModal('Entry', { resizable: true, storageKey: 'someUniqueID', sources: ['section:1', 'seciton:2'], criteria: { status: null }, multiSelect: true, disabledElementIds: [1, 2, 3], ...


12

All you need to return from the getStatuses() method is an associative array() where the key represents the status name and the value represents the status label, more or less. An example might be a set of statuses for a Payment element type: public function getStatuses() { return array( 'captured' => Craft::t('Captured'), 'canceled' ...


11

There's no such method available for craft.entries, at least it's not documented. But you can use craft.sections to get an array of section models and filter them with a conditional within a loop: {# Get all Section #} {% set sections = craft.sections.getAllSections() %} {# Loop through all single sections #} {% for singleSection in sections if ...


10

Element Types are powerful and there are probably too many possible implementations to give a very meaningful example without additional information. Here are a couple resources beyond the docs that could help you get started: Master the Elements - A comparison of all native Craft CMS Element Types and what makes them unique. Introduction to Element Types ...


6

Ok, so I've managed to get an answer to this courtesy of Brandon Kelly. It's much more simple than I thought. Firstly, you do not have to specify a relatedTo parameter the defineCriteriaAttributes(). Craft takes care of this automatically. So in order to retrieve the details of an asset in a table list view you do the following in the ...


6

There are two ways to retrieve field layouts: by ID (FieldsService::getLayoutById()) and by element type (FieldsService::getLayoutByType()). The former is useful for element types that manage multiple field layouts and have their own way of storing those field layout IDs (e.g. sections, asset sources, etc.), and the latter is useful for element types that ...


6

You’re close! You just need to begin the array with "and": $criteria = craft()->elements->getCriteria(ElementType::User); $criteria->customNumberField = array('and', '>=5', '<=10'); $users = $criteria->find(); This same thing could also be accomplished from your templates like this: {% set users = craft.users.customNumberField('and', '&...


6

The first column is reserved for whatever your element model's __toString() function returns. By default that is the element's title, if your element type has editable titles. Otherwise you will need to override that method and return whatever makes sense.


6

The Tags field classifiedTags needs an array of tag IDs, not slugs/titles. Also, if this is an existing entry and you want to retain tags already added to the field, you'll need to pull the existing tag IDs using $entry->classifiedTags->ids() and merge with those. $tag = craft()->elements->getCriteria(ElementType::Tag, [ 'groupId' => 1, ...


5

For starters I'd classify statuses in two groups - static statuses and dynamic statuses: Static statuses are set explicitly Dynamic statuses change according to other circumstances (other attribute values, lunar phases, whatever) For static statuses you'd go with the approach Lindsey outlined and just define a column for that where to store everything, ...


5

I am not really clear on what you are trying to do. My guess is you are trying to add your own validation to saving an element and trying to block that with your own custom checking of content values etc? I don't think listening to the event will help as you cannot send a message to say this element is not valid from an event listener - the event does pass ...


5

Found the answer, simple mistake. if ($criteria->code) { $query->andWhere(DbHelper::parseParam('trips.code', $criteria->code, $query->params)); } was needed along with public function defineCriteriaAttributes() { return array( 'templateId' => AttributeType::Mixed, 'code' => AttributeType::String, )...


5

I finally found the answer to this question. From BaseElementType defineAvailableTableAttributes() docs, The first item that this array returns will just identify the database column name, and the table column’s header, but will not have any effect on what shows up in the table’s body. That’s because the first column is reserved for displaying ...


4

The cleanest way to do this would be to provide your own Javascript class that overrides Craft.BaseElementIndex, which stores the latest search value in localStorage: MyElementTypeIndex = Craft.BaseElementIndex.extend( { onAfterHtmlInit: function() { // Do we have a stored search value? if (this.instanceState.searchVal) { ...


4

I looked into this a little bit... It looks like the color of the circles is dependent on one of these CSS classes by default: .status.live - Green .status.pending - Orange .status.expired - Red .status.disabled - White I'm assuming (haven't checked this) that the status gets applied to the color dot as a lowercased version of the name. So for example, if ...


4

You're bumping into this error because of a minor misunderstanding of how Pixel & Tonic are referencing their Element Types. The problem you have is with this line of code: $fieldLayout->type = ElementType::MyElementType; When P&T use that syntax, it's because they've already pre-defined all of their element types as enums. Open up the /app ...


4

Short answer: Your custom statuses will be stored in your own 3rd party table. Based on everything you've mentioned in this thread, it sounds like you've figured out how to at least define your custom statuses. Now, you'll want to store that status along with the rest of your data in your own custom table. As an example of how the status data is typically ...


4

Element Types, Custom Fields, and Sources can work closely together, but how you structure that relationship has a lot of flexibility. Sources are optional. They are a convenient way to group and filter Elements, but they vary in the way that they group those Elements – Globals use Global Sets, Categories use Category Groups, Entries use Sections – and if ...


4

In case anyone else comes up against this, here's what I did to fix it. In my PluginName_MyElementType class which inherits from BaseElementType, you need to override the defineSearchableAttributes method, returning an array containing all the names of the properties of your Model which need to be searchable. So in my case it's just name. The reason you don'...


4

Those split-style buttons are just multiple regular buttons (.btn) next to each other, wrapped in a .btngroup div: <div class="btngroup submit"> <a class="btn submit" href="#">Button One</a> <a class="btn submit" href="#">Button Two</a> </div> If you want to make one of your buttons trigger a dropdown menu, give it ...


4

You haven't defined any sources for your ElementType. <?php public function getSources($context = null) { $sources = [ '*' => [ 'label' => Craft::t('All entries'), 'criteria' => [], 'defaultSort' => ['dateUpdated', 'desc'] ] ]; return $sources; }


3

I found the solution of this was under my nose, I added this public function populateElementModel($row){ $model = Plugin_ClientModel::populateModel($row); return $model; } In Plugin_ClientElementType and then getCpEditUrl() it works.


3

You likely won't need to write a plugin at all – you can easily create different user groups (e.g. "Workers" and "Clients") from the Control Panel, and grant those groups different permissions. An example of a permission is "Access the CP". The user group permissions will be automatically applied to any new users added to the group. To create a user group, ...


3

Ok, so I finally figured it out. The trick was using the following two methods: assembleLayoutFromPost() setContentFromPost('fields') The controller now looks like this: public function actionSubmit() { // require POST $this->requirePostRequest(); // assume new element type $elementtype = new PluginName_ElementTypeModel(); // assign the attributes ...


3

That's interesting Luke, I had the exact same issue and spent WAY too long on it. Even though I used a diff tool to see the difference between working elementType models and the one with the error I just did not catch the silly difference: protected function defineAttributes() { return array( vs the working: protected function defineAttributes() { ...


3

You can only return a single content table per element query. If you need to join multiple content tables, you have two options: Use multiple element queries, one for each group of elements that share a content table. Disadvantage of this approach is, you won't be able to order elements in SQL. Just don’t join in any content tables in the initial elements ...


3

Here is a quick code summary of how this can be done. // GasTankElementType public function hasStatuses() { return true; } public function getStatuses() { return array( 'full' => Craft::t('Full Tank'), 'half' => Craft::t('Half Full/Empty'), 'empty' => Craft::t('Totally Empty'), ); } // GasTankModel // If this ...


3

You can see how this is working by opening craft/app/resources/js/craft.js and searching for the Craft.EntryIndex class definition. Craft.EntryIndex is an extension of Craft.BaseElementIndex, and is used to govern all Entry indexes in Craft (including Entry selection modals). We pull that off with this line of code, which you’ll find immediately after the ...


3

You're using $criteria, but attempting to set the relatedTo property on $this->criteria. Assuming that's not the issue, have you tried using $criteria->setAttribute('relatedTo', ['targetElement' => $category])? I've found setAttribute to be more reliable than the ElementCriteriaModel magic methods.


Only top voted, non community-wiki answers of a minimum length are eligible