CMSMadeSimple upgrade to Smarty Templating - unexpected attribute - upgrade

I'm new to CMSMS and taking an older installation through a painful upgrade path to get it to the current version. One of the major changes involves using Smarty 3 for it's templating engine. This change has broken a couple of the existing templates.
The related CMSMS module is called "Product and Inventory Manager" which looks like it's part of "Calguys Module Extensions"
Here's the error message I'm getting:
Syntax Error in template "module_db_tpl:ProductsWithLocation;summary_default" on line 26 "<h2 style="float:left;margin-right:10px;color:"#fff">{$products_path_names.$key parent=$tmp|ltrim:'-1'}</h2>" unexpected "parent" attribute
Here's the entire template that's throwing it:
{if !isset($items)}
{cgerror}<h2>Sorry! There is No material matched the query</h2>{/cgerror}
<p>Please try browsing our "full catalog" here. </p>
{else}
{if empty($products_path_names)}
{assign var='products_pagelimit' value=$actionparams.pagelimit|default:'25'}
{assign var='products_parent' value=$actionparams.hierarchyid|default:$actionparams.parent}
{assign var='products_hier_info' value=$ProductsWithLocation->GetHierarchyInfo($products_parent)}
{assign var='products_path_ids' value='.'|explode:$products_hier_info.hierarchy}
{assign var='products_path_names' value=' | '|explode:$products_hier_info.long_name}
{if !empty($products_parent) }<div style="overflow:hidden">
<h2 style="float:left;margin-right:10px">Browsing </h2>
{foreach from=$products_path_ids key='key' item='tmp' }
{if !$smarty.foreach.default.last}
{module_action_link module='ProductsWithLocation' action='hierarchy' text=$products_path_names.$key page=$page_alias parent=$tmp|ltrim:'0' pagelimit=$products_pagelimit}
{else}
<h2 style="float:left;margin-right:10px;color:"#fff">{$products_path_names.$key parent=$tmp|ltrim:'-1'}</h2>
{/if}
{/foreach}<h2 style="float:left"> Colors...</h2></div>
{/if}
{/if}
<div id="status-bar"
{if isset($pagecount) && $pagecount gt 1}
<span class="page-text">{$curpage} {$oftext} {$pagecount} {$pagetext} </span>
<ul class="paging">
<li>{$firstlink}</li><li>{$prevlink}</li> <li>{$nextlink}</li><li>{$lastlink}</li></ul>
{/if}
Switch Thumb
{if $products_parent !=13 }
<a class="a-z" href="{$products_path_names.$key}_Index.htm">{$products_path_names.$key}</a>
{else}
{/if}
</div>
<ul class="gallery">
{foreach from=$items item=entry}
{*
the summary template has access to custom fields via the $entry->fields hash
and to categories via the $entry->categories array of objects. Also
attribute information is available via $entry->attributes.
you should use the get_template_vars and the print_r modifier to see
what is available
*}
{if $products_parent == 13 }
<li>
<dl>
<dt><a class="tip_trigger more-stone-info" href="{$entry->detail_url}">{$entry->product_name}<span class="tip">More information about <strong style="color:#9BD8EB">{$entry->product_name}</strong></span></a></dt>
{* accessing all of the fields in a list *}
{if isset($entry->fields)}
{foreach from=$entry->fields key='name' item='field'}
{if isset($field->value)}
{if $field->type == 'checkbox' or $field->type == 'image' && isset($field->thumbnail)}
{else}
{/if}
{if $field->type == 'image' && isset($field->thumbnail)}
<span class="tip">More information about <strong style="color:#9BD8EB">{$entry->product_name}</strong></span><img src="{$entry->file_location}/{$field->thumbnail}" alt="{$field->value}"/>
{/if}
{/if}
{/foreach}
{/if}
{assign var='hinfo' value=$ProductsWithLocation->GetHierarchyInfo($entry->hierarchy_id)}
<dd><em>Stone Type: </em>Cambria Quartz</dd>
<dd><em>Collection: </em>{module_action_link module=ProductsWithLocation action=default hierarchyid=$entry->hierarchy_id text=$hinfo.name}</dd>
</dl>
</li>
{else}
<li>
<dl>
<dt><a class="tip_trigger more-stone-info" href="{$entry->detail_url}">{$entry->product_name}<span class="tip">More information about <strong style="color:#9BD8EB">{$entry->product_name}</strong></span></a></dt>
{* accessing all of the fields in a list *}
{if isset($entry->fields)}
{foreach from=$entry->fields key='name' item='field'}
{if isset($field->value) && $field->name != 'GalleryFolder'}
{if $field->type == 'checkbox' or $field->type == 'image' && isset($field->thumbnail)}
{else}
<dd><em>
{$name}
</em>
{if is_array($field->value)}
{if !empty($field->value) }
{foreach from=$field->value item='val'}
{if $field->type == 'image' && isset($field->thumbnail)}
{else}
{module_action_link module=$mod->GetName() action=default fieldid=$field->id fieldval=$val text=$val} {/if}
{/foreach}
{/if}
{else}
{if $field->type == 'image' && isset($field->thumbnail)}
{else}
{module_action_link module=$mod->GetName() action=default fieldid=$field->id fieldval=$field->value text=$field->value} {/if}
{/if}
</dd>
{/if}
{if $field->type == 'image' && isset($field->thumbnail)}
<span class="tip">More information about <strong style="color:#9BD8EB">{$entry->product_name}</strong></span><img src="{$entry->file_location}/{$field->thumbnail}" alt="{$field->value}"/>
{/if}
{/if}
{/foreach}
{/if}
{assign var='hinfo' value=$ProductsWithLocation->GetHierarchyInfo($entry->hierarchy_id)}
<dd><em>Stone Type: </em>{module_action_link module=ProductsWithLocation action=default hierarchyid=$entry->hierarchy_id text=$hinfo.name}</dd>
</dl>
</li>
{/if}
{/foreach}
</ul>{/if}
Here's the relevant snip of that template where the error occurs:
{$products_path_names.$key parent=$tmp|ltrim:'-1'}</h2>
From what I understand we're calling a custom function with a name based on products we have in our database. We're sending it an attribute "parent" which it's not expecting. If I remove that attribute the error goes away but the output gets weird.
Short of a magic bullet I think any clues where to look for this function being defined would help me. I'm also baffled by the use of what appears to be ltrim("-1") so any explanation of that would also be nice. Maybe I can replace this line with a longer if block to correct the function call?
Edit - Here's some sample values for the variables:
$products_path_names.$key holds string 'Granite'
$tmp holds string 00017
Thanks!

I more or less solved it. I got rid of the parent attribute entirely and fixed the weird output by changing this line:
{if !$smarty.foreach.default.last}
to
{if $smarty.foreach.default.last != ''}
It was not counting an empty string as false.
Seems to work now.

Related

Why validation is not working?

corporate.html
<form #f="ngForm" name="corporateProfileForm" ng-submit="corporateFrmSave(objDS, objDSCurrency)" novalidate="">
<div class="row form-group">
<div class="col-md-12" >
<input type="text" *ngIf="formData" [(ngModel)]="formData.Corporate_Id" id="corpid" title="Corporate ID" tab-index="1" name="corpid" maxlength="20" #corpid="ngModel" required/>
<label for="corp"><b>Corporate ID</b></label>
<div *ngIf="corpid.invalid && (corpid.dirty || corpid.touched)" class="alert alert-danger">
<div *ngIf="corpid.errors.required">
Name is required.
</div>
<div *ngIf="ncorpidame.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="corpid.errors.forbiddenName">
Name cannot be Bob.
</div>
</div>
</div>
</div>
</form>
Iam getting error message as
ERROR TypeError: Cannot read property 'invalid' of undefined
Make sure you define your variable with this structure:
TS file
export class ContactComponent implements OnInit {
myform: any;
corpid: FormControl;
constructor() {
}
ngOnInit() {
this.createFormControls();
this.createForm();
}
createFormControls() {
this.corpid= new FormControl('', Validators.required);
}
createForm() {
this.myform = new FormGroup({
corpid: this.corpid,
});
}
HTML file
<div class="md-form form-sm form-group"
[ngClass]="{
'invalid': corpid.invalid && (corpid.dirty || corpid.touched),
'valid': corpid.valid && (corpid.dirty || corpid.touched)
}">
<i class="fa fa-user prefix"></i>
<input
type="text" id="corpid" class="form-control"
required
[formControlName]="'corpid'">
<label for="corpid" class="">Your corpid</label>
</div>
<div class="form-control-feedback"
*ngIf="corpid.errors && (corpid.dirty || corpid.touched)">
<p *ngIf="corpid.errors.required">corpid is required</p>
</div>
It's hard to tell because issue is not in your HTML snipped but in .ts file.
I hope my Code will be helpfull
The issue is with the *ngIf, so when that condition is checked, Angular renders the rest of the template, and while the small fraction of time while *ngIf is being evaluated, your template reference variable corpid does not exist, so it will throw an error when trying to check the validation intially.
Wrap the input field with the validation div's inside the *ngIf instead of applying it only on the input field.
<div class="row form-group" *ngIf="formData">
<input [(ngModel)]="formData.Corporate_Id" id="corpid" ... >
<!-- more code here... -->
</div>
DEMO

CMSMS - CGBlog how to output html for all but last entry?

I'm new to CMSMS and am using CGblog where I have a listing template and everything is working fine except that I need to stop an HR tag from displaying on the last item. Can't figure out the correct way to code this.
CMS Made Simple™ 1.11.10 “Pinzon”
{foreach from=$items item=entry}
<div class="CGBlogSummary">
<article>
<h3>{$entry->title|escape}</h3>
<p style="font-size: 12px;">{if $entry->author}Written by {$entry->author}{/if}{if $entry->postdate} on {$entry->postdate|cms_date_format}.{/if}</p>
<div class="row">
<div class="large-6 columns">
{if isset($entry->extra)}
<div class="CGBlogSummaryExtra">
{eval var=$entry->extra}
{ {cms_module module='Uploads' mode='simpleurl' upload_id=$entry->extravalue} }
</div>
{/if}
{if isset($entry->fields)}
{foreach from=$entry->fields item='field'}
<div class="CGBlogSummaryField">
{if $field->type == 'file'}
<img src="{$entry->file_location}/{$field->value}"/>
{else}
{$field->name}: {eval var=$field->value}
{/if}
</div>
{/foreach}
{/if}
</div>
<div class="large-6 columns">
{if $entry->summary}
{eval var=$entry->summary}
{else if $entry->content}
{eval var=$entry->content}
{/if}
<p>Read more...</p>
</div>
</div>
</article>
<hr /><!-- this should not be output on the final iteration of the loop-->
</div>
{/foreach}
You can simple change this line:
<hr /><!-- this should not be output on the final iteration of the loop-->
into
{if not $entry#last}<hr />{/if}
I believe you can use syntax as such:
<hr {if $entry#last} style='display:none' {/if} />
(hides the hr using css if its the last entry), quick and dirty though!

CMSMS formbuilder template

I hope somebody here is using CMSMS and will help me with a piece of advice.
I've been struggling for two days to find an answer. I'm quite new to this cms.
I need a two column form - half in left div and the other half in the right div.
The question is how do I arrange items (input + labels) with a specific class using smarty templates?
I've tried something like this:
{if $entry->css_class=='formgroup-right'}
<div class="right-side">
...............
</div>
{/if}
but it doesn't include all divs into one. I need to just modify the default formbuilder template. I need a pattern. I don't know if it's possible at all to do this using smarty.
{if $entry->css_class=='formgroup-right'} // if entry css class is equal to formgroup-right then include all of them into div.right-side
<div class="right-side">
{foreach from=$fields item=entry}
{if $entry->display == 1}
{strip}
{if $entry->needs_div == 1}
<div
{if $entry->required == 1 || $entry->css_class != ''} class="
{if $entry->required == 1}
required
{/if}
{if $entry->required == 1 && $entry->css_class != ''} {/if}
{if $entry->css_class != ''}
{$entry->css_class}
{/if}
"
{/if}
>
{/if}
.................................................
{/if}
{/foreach}
</div>
{/if}
Well you are a little vague here but if all you want is all inputs with class formgroup-right in a
<div class="right-side"> ... </div>
and all with class formgroup-left in a
<div class="left-side"> ... </div>
First arrange all fields for left together and all for right together
100 field A -left side
102 field C -left side
104 field E -left side give this class last-left
101 field B -right side
103 field D -right side
104 field F -right side
Then in your form template
{assign var=side value=0}
<div class="left-side">
{foreach from=$fields item=entry}
{if $entry->display == 1}
...................
{if $entry->css_class == 'last-left'}
</div> <!-- end of left side -->
<div class="right-side">
{/if}
{/if}
{/foreach}
</div> <!-- end of right side -->
This will go through the fields in the order you have arranged them and place the first fields in the left side div until it get to the last when it will close the div and open the right div.
That is if I understand your problem.

How to parse many div's using Simple HTML DOM?

I have this HTML code
<div id="first" class="first">
One
<div id="second" class="second">
Second
<div id="third" class="third">
Third
<div id="fourth" class="fourth">
Fourth
<div id="fifth" clas="fifth">
Fifht
<div id="sixth" class="sixth">
Sixth
</div>
</div>
</div>
</div>
</div>
</div>
This code is from an external website.
I want to display 'Hi' using Simple HTML DOM from a URL.
Do you want to see something like this?
$el = $html->find("#first", 0);
while ($child = $el->children(1)) {
$el = $child;
}
echo $el->innertext;

afterAdd binding is not working

I tried to use the afterAdd binding to add some trivial animation to the elements being added to my observableArray but it does not trigger anything.
I tought I had a problem with my animation code so I coded a small alert on the function but still does not work.
Here's some sample code for the div being templated:
<div id="resultList"
data-bind='template: { name: "searchResultTemplate",
afterAdd: function(elem){alert(elem)} }'
runat="server">
</div>
This is the template:
<script type="text/html" id="searchResultTemplate">{{each(i, searchresult) resultCollection()}}
<div class="searchresultwrapper ui-corner-all ui-state-default">
<div class="searchresult">
<img src='${ ImageUrl }' alt='${ Title }' title='${ Title }' class="searchresultpicture" />
<div class="searchresultinformationcontainer">
<span class="searchresulttitle" data-bind="text: Title"></span>
<br />
<div class="searchresultdescription" data-bind="text: Description">
</div>
<span class="searchresultAuthor" data-bind="text: AuthorName"></span> at <span class="searchresultmodule" data-bind="text: ModuleName"></span> on <span class="searchresultdate" data-bind="text: PublicationDate"></span>
<br />
Take me there
</div>
</div>
</div>
<br />{{/each}}
</script>
Any ideas?
You need to qualify the template attributes with foreach like so,
<div id="resultList" data-bind='template: {
name: "searchResultTemplate",
foreach: searchresult,
beforeRemove: function(elem) { $(elem).slideUp() },
afterAdd: function(elem) { $(elem).hide().slideDown() }
}' runat="server">
</div>
and then, not use {{each in the template, just template it for each item stand alone.
Here, foreach attribute helps keep track of changes to the object array