Build dynamic navigation with list headers (coldfusion & cfscript) - coldfusion

For a project im building a navigation. The table is like this
SELECT TOP 1000
[id]
,[title]
,[action]
,[listOrder]
,[fk_parentId]
FROM [portfolio].[dbo].[menu]
Where Fk_parentId refers to a id... to build up a menu with levels. Listorder contains a number
Now i want my navigation to output like this
<ul class="nav nav-list">
<li class="nav-header active">List header</li>
<li class="active">Home</li>
<li>Library</li>
<li>Applications</li>
<li class="nav-header">Another list header</li>
<li>Profile</li>
<li>Settings</li>
<li class="divider"></li>
<li>Help</li>
</ul>
so the nav headers must be detected as a nav header and menu items as child. For now i have this code
public void function main(struct rc) {
queryService = new query();
queryService.setDatasource("portfolio");
result = queryService.execute(sql="SELECT * FROM menu ORDER by listOrder");
// result
GetMenuData = result.getResult();
// Loopen over result
writeOutput("<ul class='nav nav-list>'");
for (i = 1; i LTE GetMenuData.RecordCount; i = (i + 1))
{
// Output
WriteOutput(
"<li><a href='"& GetMenuData[ "action" ][ i ] & "'>" & GetMenuData[ "title" ][ i ] & "</a></li>"
);
}
writeOutput("</ul>'");
}
this results:
<ul class='nav nav-list>'
<li><a href='alk.profile'>PROFILE</a></li>
<li><a href=''>List header</a></li>
<li><a href='main.'>home</a></li>
<li><a href=''>Another List header</a></li>
<li><a href='alh.settings'>settings</a></li>
<li><a href='main.library'>librarY</a></li>
<li><a href='help.main'>Help</a></li>
<li><a href='main.applications'>applications</a></li>
</ul>'
How can I add class header to a "header" <li> like listheader, another list header?
How can i dynamicly add the divider between settings and help?
title action listOrder fk_parentId
Another List header NULL 20 NULL
PROFILE alk.profile 5 539BB1A4-5AB5-4059-93AD-17DD8EABAF60
Help help.main 40 NULL
settings alh.settings 20 539BB1A4-5AB5-4059-93AD-17DD8EABAF60
applications main.applications 50 C5EFAE69-FD2A-4B35-A613-B8D429091A8F
List header NULL 10 NULL
home main. 20 C5EFAE69-FD2A-4B35-A613-B8D429091A8F
librarY main.library 30 C5EFAE69-FD2A-4B35-A613-B8D429091A8F

I can't see how you specify active from what you posted, but the following at least would result in the function returning the list with header classes.
public string function main(struct rc) {
// Set up the return string
var strReturn = '<ul class="nav nav-list">';
// Set up the query
var queryService = new Query(
datasource='portfolio'
);
// Execute and get result, specifying field names
var GetMenuData = queryService.execute(sql='
SELECT
id,
action,
title,
fk_parentId
FROM menu
ORDER by listOrder ASC
').getResult();
// Loop over result
for (var i = 1; i <= GetMenuData.RecordCount; i++) {
// For this result, what classes are needed?
var strClasses = '';
// Header class
if (
Len(GetMenuData['fk_parentId'][ i ]) == 0 // Null / len 0 parent == header
) {
strClasses = ListAppend(strClasses,'nav-header',' ');
}
// Add in some logic here for 'active' later on probably a good idea?
// strClasses = ListAppend(strClasses,'active',' ') if id == active id? May need adjustment to query for parent
if (
Len(strClasses) > 0
) {
strClasses = ' class="'&strClasses&'"';
}
// Output list item
strReturn &= '<li'&strClasses&'>';
// Add href if needed
if (
Len(GetMenuData['action'][ i ]) > 0
) {
strReturn &= '<a href="'&GetMenuData['action'][ i ]&'">';
}
strReturn &= GetMenuData['title'][ i ];
if (
Len(GetMenuData['action'][ i ]) > 0
) {
strReturn &= '</a>';
}
// Close off the list item
strReturn &= '</li>';
}
// End the return string
strReturn &= '</ul>';
// And return it
return strReturn;
}
A few notes on the changes
Changed function to have return type "string" instead of "void" and modified it so it returns a string instead of directly writing. This in general allows more control over where precisely the list would be output.
Added scoping for all variables invoked within the function (using 'var' keyword). Please note that the below example will only work in CF9/railo. If using a previous version then the var definitions need to be at top of the function, if unsure just ask
Left a space to indicate where you would add in logic for flagging "active"
Used i++ in place of i = (i + 1) (see What is the difference between ++i and i++? for some info for what that does)
Used strReturn &= ... to add to string, functionally equivilant to strReturn = strReturn & ....

Related

Want to copy US format phone number

I want to copy a US format phone number and paste it to my field .
If I copy (456)-123-0596 to the field only 456123 is copied to the field.
But I want it to be like the format.
The input field is restricted only for numbers using pattern and maximum length is 10.
onCheckInput(e) {
const onlyNums = e.target.value.replace(/[^0-9]/g, '');
if (onlyNums.length < 10) {
e.target.value = onlyNums;
} else if (onlyNums.length === 10) {
const number = onlyNums.replace(/(\d{3})(\d{3})(\d{4})/, '($1) -$2-$3');
e.target.value = number;
}
}
formatPhoneNumber(number) {
if (number && number != 0) {
number = number.replace(/-/g, '');
number = number.replace('(', '');
number = number.replace(') ', '');
number = number.replace(')', '');
return '(' + number.substr(0, 3) + ')-' + number.substr(3, 3) + '-' + number.substr(6, 4);
}
return '';
}
<Field name="HomePhone"
onInput={this.onCheckInput} maxLength="10"
pattern="\d*" component="input" type="text"
placeholder="HomePhone"
title={' Home Phone: ' + this.formatPhoneNumber(patientInfo.HomePhone)}
/>
How can I remove the braces and hyphens on Paste and save them in the Phone number format?
I've modified the code as below:
onCheckInput(e) {
const onlyNums = e.target.value.replace(/[^0-9]/g, '');
if (onlyNums != e.target.value.replace(/[^\d\.]/g,""))
{onlyNums.replace(/[^\d\.]/g,"");
}
if (onlyNums.length < 10) {
e.target.value = onlyNums;
} else if (onlyNums.length === 10) {
const number = onlyNums.replace(/(\d{3})(\d{3})(\d{4})/, '($1) -$2-$3');
e.target.value = number;
}
}
When I debugged I found that
Since maxLength1s 10 (456)-123- is read and removed braces and hyphens from this input.
How can I get this format with maxLength=10?
I think this approach can solve your problem:
Listen paste event, when it happens increment maxLength property to 1000, then clean the input and set it again to the input value.
I have implemented it in plain DOM because I don't know react, you can use the same approach to implement it in React
const input = document.querySelector('#HomePhone');
input.addEventListener('paste', (event) => {
// Imcrement maxLengt temporally so user can paste input with ( -
input.maxLength=1000
setTimeout(()=>{
// clean input: only get numbers
const result = input.value.replace(/[^\d]/g,'')
// set the clean input into input value
input.value=result
// reset maxLength to 10
input.maxLength=10
}, 1);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input name="HomePhone" id="HomePhone" maxLength="10" type="text" pattern="\d*" />
</body>
</html>

Drupal7 custom menu code in template adds stray div for no reason

I am hoping someone more knowledgeable here can point out what the problem is.
I am making a custom menu for Drupal7 for a particular theme I am working on, which is using the menu_views module. Everything works pretty nicely until I pass the view menu entry over to menu_views to parse, in which case drupal adds a broken <div class=">...</div> around the parent UL element of the view menu.. I have gone through the code and don't see how this is even happening.. If I comment out the call to the view parsing, then it doesn't add this DIV, but that view parsing shouldnt' be touching the parent UL element?
Here is how the HTML is output:
<ul class="sub-menu collapse" id="parent_">
<div class="> <li class=" first=" " expanded=" " active-trail "=" ">Por nome
<ul class="menu-content collapsed in " id=" ">
<div class="view view-nameofview view-id-nameofview etc ">
<div class="view-content ">
<div class="item-list ">
<ul class="views-summary ">
<li>Á
</li>
</ul>
</div>
</div>
</div>
</ul>
</div>
</ul>
Here is the template code that causes this:
function bstheme_menu_link__main_menu($variables) {
$element = $variables['element'];
// resolve conflict with menu_views module
if (module_exists('menu_views') && $element['#href'] == '<view>') {
return _bstheme_menu_views_menu_link($variables); //<<<< IF I COMMENT OUT THIS THE OUTPUT IS FINE
}
static $item_id = 0;
// Add an ID for easy identifying in jquery and such
$element['#attributes']['id'] = 'menu_'.str_replace(' ', '_',strtolower($element['#title']));
if(!empty($element['#original_link']['menu_name']) && $element['#original_link']['menu_name'] == 'main-menu'){
if($element['#original_link']['has_children'] == 1){
$element['#attributes']['data-target'] = "jquery_updates_this";
$element['#attributes']['data-toggle'] = "collapse";
}
// add class parent and remove leaf
$classes_count = count($element['#attributes']['class']);
for($i=0;$i<$classes_count;++$i){
if($element['#attributes']['class'][$i] == 'expanded'){
//$element['#attributes']['class'][$i] = 'collapse';
}
if($element['#original_link']['plid'] == 0){
if($element['#attributes']['class'][$i] == 'leaf'){
unset($element['#attributes']['class'][$i]);
}
}
else{
if($element['#attributes']['class'][$i] == 'leaf'){
$element['#attributes']['class'][$i] = '';
}
}
}
}
// code to add a span item for the glythicons
$switch = $element['#original_link']['has_children'];
$element['#localized_options']['html'] = TRUE;
if($switch == 1) {
$linktext = $element['#title'] . '<span class="arrow"></span>';
} else {
$linktext = $element['#title'];
}
// if there's a submenu, send the parsing to the custom function instead of the main one to wrap different classes
if ($element['#below']) {
foreach ($element['#below'] as $key => $val) {
if (is_numeric($key)) {
$element['#below'][$key]['#theme'] = 'menu_link__main_menu_inner'; // 2 lavel
}
}
$element['#below']['#theme_wrappers'][0] = 'menu_tree__main_menu_inner'; // 2 lavel
$sub_menu = drupal_render($element['#below']);
$element['#attributes']['class'][] = 'menu-toggle';
}
//$sub_menu = $element['#below'] ? drupal_render($element['#below']) : '';
$output = l($linktext, $element['#href'], $element['#localized_options']);
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . '</li>'."\n";
}
function _bstheme_menu_views_menu_link(&$variables) {
// Only intercept if this menu link is a view.
$view = _menu_views_replace_menu_item($variables['element']);// <<< MENU VIEWS PARSING
if ($view !== FALSE) {
if (!empty($view)) {
$sub_menu = '';
if ($variables['element']['#below']) {
$sub_menu = render($variables['element']['#below']);
}
return '' . $view . $sub_menu . "\n"; // <<< RETURN PATH
}
return '';
}
return theme('menu_views_menu_link_default', $variables);
}
Any pointers on how to troubleshoot something like this, or if someone has encountered this problem before and has a solution, would be greatly helpful!
From your code, it's apparent you're using Drupal 7.
First things first, you may want to enable theme debug mode. This allows for you to see where the theming function that caused your
You can do so by putting the following line in your settings.php file
$conf['theme_debug'] = TRUE;
Flush your caches after you make this change.
You will now have debug code output to your Drupal HTML source, when you view the site's source. An example of the type of output is shown below:
<!-- THEME DEBUG -->
<!-- CALL: theme('page') -->
<!-- FILE NAME SUGGESTIONS:
x page--front.tpl.php
* page--node.tpl.php
* page.tpl.php
-->
With this debug, you should be able to see exactly which theme functions run, in which order, and by working through them from start to finish, you should be able to determine between which theme is responsible.
At this point, if you want to keep Drupal-best-practices, copy the file name suggestion from the debug output to a folder inside your theme folder. I usually put all template overrides in a sub-directory inside it.
In the case above, if it was page.tpl.php, I'd copy it to /themes/mytheme/templates/, and go hack on it to see whether the offending div is being generated there.
Best of luck, and if you hit a stuck end, I'd be happy to help point you in a direction more specific to your specific user case.
Best,
Karl

VirtueMart 2.6.6 custom field (cart variable) not displayed in the order details

I programmed a custom field plugin for Virtuemart 2.6.6, which show some parameters on the product page for example "size", and that parameter is a cart variable either.
A huge help was this article:
https://www.spiralscripts.co.uk/Joomla-Tips/custom-plugin-fields-in-virtuemart-2-2.html
And of course stackoverflow forum and factory default VM custom plugins.
Everything is working (the size is displayed in product details view, and in the cart, when you added the product to it) but one thing:
after sending the order the parameter has not displayed in the order details, so I don't know what size of product was bought.
I placed following functions into my plugin, but not solved my problem:
function plgVmOnViewCart($product, $row, &$html)
{
if (empty($product->productCustom->custom_element) or $product->productCustom->custom_element != $this->_name) return '';
if (!$plgParam = $this->GetPluginInCart($product)) return false ;
$html .= '<div class="parameterek_attributes">';
foreach ($plgParam as $attributes) {
foreach ($attributes as $k => $attribute) {
if ($k =='child_id') continue;
if ($k == 'custom_param_default3') $name = 'Veľkosť'; else $name = '';
$html .='<span class="parameterek_attribute"> '.$name.': '.JText::_($attribute).' </span>';
}
}
$html.='</div>';
return true;
}
/**
*
* shopper order display BackEnd
*/
function plgVmDisplayInOrderBE($item, $row,&$html)
{
if (empty($item->productCustom->custom_element) or $item->productCustom->custom_element != $this->_name) return '';
if(!empty($productCustom)){
$item->productCustom = $productCustom;
}
$this->plgVmOnViewCart($item, $row,$html);
}
/**
*
* shopper order display FrontEnd
*/
function plgVmDisplayInOrderFE($item, $row,&$html)
{
if (empty($item->productCustom->custom_element) or $item->productCustom->custom_element != $this->_name) return '';
$this->plgVmOnViewCart($item, $row,$html);
}
Into database table called #__virtuemart_order_items were saved values: something like:
{"357":"5"}
but it should be something like:
{"357":"size M"}
I see that the key function is GetPluginInCart($product), and when I printed out the $product->param in that function I've got this output, when I go through checkout process:
Array
(
[0] => Array
(
[parameterek] => Array
(
[custom_param_default3] => L
)
)
)
but after I finish the order and go into order details the $product->param has this value:
Array
(
[357] => 5
)
So I think, before I finish the order I have to somehow handle the
chosen product parameter and transform it into the correct form, but
I don't know how.
On the following site
https://dev.virtuemart.net/projects/virtuemart/wiki/Product_Plugins
I found a function:
plgVmOnViewCartOrder($product, $param,$productCustom, $row)
handel $param before adding it in the order
return $param;
but when I searched for the string "plgVmOnViewCartOrder" in the whole virtuemart installation, it was not found, so it means it is not launched (?)
If anybody could help me or send a fair documentation would be very good. Thank you!
I think, I solved my problem, what was:
in function plgVmOnDisplayProductVariantFE I made a mistake, I didn't use layout renderer, which generates an object $viewData with variable virtuemart_customfield_id.
Then in your plugin's layout, input field name has to be as follows:
<input
class="parameterekInput"
type="radio"
id="plugin_param['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.']['.$c.']"
name="customPlugin['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.'][custom_param_default3]"
value="'.$size.'" />
so the name attribute should be always:
customPlugin['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.'][whatever]
The right usage of plgVmOnDisplayProductVariantFE function is to use expression:
$group->display .= $this->renderByLayout('default',array($field,&$idx,&$group )
Here the whole function with the right expresion:
function plgVmOnDisplayProductVariantFE ($field, &$idx, &$group) {
if ($field->custom_element != $this->_name) return '';
$this->getCustomParams($field);
$this->getPluginCustomData($field, $field->virtuemart_product_id);
$group->display .= $this->renderByLayout('default',array($field,&$idx,&$group ) );
return true;
}
Now when I print_r -ing $product->param in function GetPluginInCart($product), I get this:
Array
(
[273] => Array //previously the key was Zero, now it is 273, value of virtuemart_customfield_id
(
[parameterek] => Array
(
[custom_param_default3] => L
)
)
)
...and now I'm glad, that I can move on in my project :)

Does anybody know how to add meta box template select to custom post type in Wordpress?

does anybody know how I can achieve the following:
I have a custom post type called 'projects' I have 5 different page
layouts (each with a different number of images at different sizes
that are arranged differently). I think that if I can ID the images I
can position them using CSS. If each layout has it's own template page
with containers for the required images and each also has CSS to
position the images.
I am wondering if it's possible to add a
template select on right hand side of post editor view, like you have
available for pages this way it's possible to assign a template (from
1-5) for each post.
I am adding custom meta boxes for the image upload fields
and the other data in the main post editor, but ideally this should
change for the other pages to only display the required upload
fields.
Any ideas anybody? I did consider setting up a custom post type for each layout (the 5 templates) allowing you to post a new project under the layout type you require, then on the page query the loop with all 5 custom-post-types (layouts). I worry this might be messy though, because to find projects to edit later you will need to know which template page (custom-post-type) they belong to but more importantly the url to projects wouldn't be www.sitename.co.uk/projects but instead be www.sitename.co.uk/custom-post-type1, www.sitename.co.uk/custom-post-type2 ??? Wouldn't it?
Any help really appreciated as always. Thanks
here is code I have identified so far, any ideas how to customise?
Should this go in functions.php?
// Check if the post has a special template
$template = get_post_meta($post->ID, '_wp_mf_page_template', true);
if (!$template || $template == 'default') {
return;
}
$template = TEMPLATEPATH.'/'.$template;
if ( $template = apply_filters( 'template_include', $template ) ) {
include($template);
die();
}
return;
Second code:
// Check if the post_type has page attributes
// if is the case is necessary need save the page_template
if ($_POST['post_type'] != 'page' && isset($_POST['page_template'])) {
add_post_meta($post_id, '_wp_mf_page_template', $_POST['page_template'], true) or update_post_meta($post_id, '_wp_mf_page_template', $_POST['page_template']);
}
Third code:
//MF Meta box for select template
function mf_metabox_template () {
global $post;
if ( 0 != count( get_page_templates() ) ) {
$template = get_post_meta($post->ID, '_wp_mf_page_template', TRUE);
$template = ($template != '') ? $template : false;
?>
<label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php page_template_dropdown($template); ?>
</select>
<?php
}
}
You can create meta box using this code. Please paste this code in your function.php.
/*********************custom meta box********************************/
add_action( 'add_meta_boxes', 'add_events_metaboxes' );
function add_events_metaboxes() {
add_meta_box('wpt_school_location', 'Business Listing Data:','wpt_school_location', 'businesses', 'side', 'default');
}
//add_meta_box( $id, $title, $callback, $page, $context, $priority, $callback_args );
// Add the Events Meta Boxes
// The Event Location Metabox
function wpt_school_location() {
global $post;
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the location data if its already been entered
$email = get_post_meta($post->ID, '_location', true);
$tel = get_post_meta($post->ID, '_location1', true);
$web = get_post_meta($post->ID, '_location2', true);
$city = get_post_meta($post->ID, '_location3', true);
// Echo out the field
echo '<div class="heading">Address</div>';
echo '<input type="text" name="_location" value="' . $email . '" class="widefat" />';
echo '<div class="heading">Telephone</div>';
echo '<input type="text" name="_location1" value="' . $tel . '" class="widefat" />';
echo '<div class="heading">E-mail</div>';
echo '<input type="text" name="_location2" value="' . $web . '" class="widefat" />';
echo '<div class="heading">Web</div>';
echo '<input type="text" name="_location3" value="' . $city . '" class="widefat" />';
}
// Save the Metabox Data
function wpt_save_events_meta($post_id, $post) {
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['eventmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
// OK, we're authenticated: we need to find and save the data
// We'll put it into an array to make it easier to loop though.
$events_meta['_location'] = $_POST['_location'];
$events_meta['_location1'] = $_POST['_location1'];
$events_meta['_location2'] = $_POST['_location2'];
$events_meta['_location3'] = $_POST['_location3'];
// Add values of $events_meta as custom fields
foreach ($events_meta as $key => $value) { // Cycle through the $events_meta array!
if( $post->post_type == 'revision' ) return; // Don't store custom data twice
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // If the custom field doesn't have a value
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key); // Delete if blank
}
}
add_action('save_post', 'wpt_save_events_meta', 1, 2); // save the custom fields
// Add the Events Meta Boxes

angularjs if statements?

So I'm running through the tutorial for AngularJS:
I have an array defined in the controller and i'm returning different points in the array by calling when i'm looping through ng-repeat {{feature.name}} {{feature.description}}
What i don't understand is lets say i have a third point in the array called "importance" and it's a number from 1 to 10. I don't want to display that number in the html but what i do want to do is apply a different color to the feature if that "importance" number in the array is 10 vs 1
so how do i write an if statement to do this:
i.e.
<p style="**insert if statement: {{if feature.importance == 10}} color:red; {{/if}} **">{{feature.description}}</p>
no idea if that's right but that's what i want to do
I do not think there is if statement available.
For your styling purpose, ng-class can be used.
<p ng-class="{important: feature.importance == 10 }">
ng-switch is also convenient.
-- update --
take a look at:
https://stackoverflow.com/a/18021855/1238847
angular1.2.0RC seems to have ng-if support.
Actually there is a ternary operator in Angular 1.2.0.
<p style="{{feature.importance == 10 ? 'color:red' : ''}}">{{feature.description}}</p>
I think the answer needs an update.
Previously you could use ngIf directive from AngularUI project (code here if you still want to download it), bad news is that it's not maintained any more.
The good news is that it has been added to the official AngularJS repo (unstable branch) and soon will be available in the stable one.
<div ng-if="something"> Foo bar </div>
Will not just hide the DIV element, but remove it from DOM as well (when something is falsy).
ng-class is probably the best answer to your issue, but AngularUI has an "if" directive:
http://angular-ui.github.com/
search for:
Remove elements from the DOM completely instead of just hiding it.
I used "ui-if" to decide if I should render a data value as a label or an input, relative to the current month:
<tbody id="allocationTableBody">
<tr ng-repeat="a in data.allocations">
<td>{{a.monthAbrv}}</td>
<td ui-if="$index < currentMonth">{{a.amounts[0]}}</td>
</tr>
</tbody>
In the case where your priority would be a label, you could create a switch filter to use inside of ng-class as shown in a previous SO answer : https://stackoverflow.com/a/8309832/1036025 (for the switch filter code)
<p ng-class="feature.importance|switch:{'Urgent':'red', 'Warning': 'orange', 'Normal': 'green'}">...</p>
You can also try this line of code below
<div class="{{is_foo && foo.bar}}">
which shows foo.bar if is_foo is true.
This first one is a directive that evaluates whether something should be in the DOM only once and adds no watch listeners to the page:
angular.module('setIf',[]).directive('setIf',function () {
return {
transclude: 'element',
priority: 1000,
terminal: true,
restrict: 'A',
compile: function (element, attr, linker) {
return function (scope, iterStartElement, attr) {
if(attr.waitFor) {
var wait = scope.$watch(attr.waitFor,function(nv,ov){
if(nv) {
build();
wait();
}
});
} else {
build();
}
function build() {
iterStartElement[0].doNotMove = true;
var expression = attr.setIf;
var value = scope.$eval(expression);
if (value) {
linker(scope, function (clone) {
iterStartElement.after(clone);
clone.removeAttr('set-if');
clone.removeAttr('wait-for');
});
}
}
};
}
};
});
This second one is a directive that conditionally applies attributes to elements only once without watch listeners:
i.e.
<div set-attr="{ data-id : post.id, data-name : { value : post.name, condition : post.name != 'FOO' } }"></div>
angular.module('setAttr',[]).directive('setAttr', function() {
return {
restrict: 'A',
priority: 100,
link: function(scope,elem,attrs) {
if(attrs.setAttr.indexOf('{') != -1 && attrs.setAttr.indexOf('}') != -1) {
//you could just angular.isObject(scope.$eval(attrs.setAttr)) for the above but I needed it this way
var data = scope.$eval(attrs.setAttr);
angular.forEach(data, function(v,k){
if(angular.isObject(v)) {
if(v.value && v.condition) {
elem.attr(k,v.value);
elem.removeAttr('set-attr');
}
} else {
elem.attr(k,v);
elem.removeAttr('set-attr');
}
});
}
}
}
});
Of course your can use dynamic versions built into angular:
<div ng-class="{ 'myclass' : item.iscool }"></div>
You can also use the new ng-if added by angularjs which basically replaces ui-if created by the angularui team these will conditionally add and remove things from the DOM and add watch listeners to keep evaluating:
<div ng-if="item.iscool"></div>
What also works is:
<span>{{ varWithValue || 'If empty use this string' }}</span>