angular2 - adding 'pattern' for form builder - regex

I have a pattern for a form builder and I have this:
this.userForm = this.formBuilder.group({
'postalCode': ['', Validators.pattern('/[A-Za-z][0-9][A-Za-z] [0-9][A-Za-z][0-9]/i')]
});
I have a ValidationService which I've added a function "getValidatorErrorMessage".
static getValidatorErrorMessage(validatorName: string, validatorValue?: any) {
let config = {
'pattern': 'invalid pattern'
};
return config[validatorName];
}
My template has:
<div>
<label for="postalCode">Postal code (A1A 2J3)</label>
<input formControlName="postalCode" id="postalCode" />
<control-messages [control]="userForm.controls.postalCode"></control-messages>
</div>
But for some odd reason, the validation messages arent displaying if I dont follow the regex code.
You can view the plunkr here.

That's because you set a condition in your ControlMessagesComponent that input field has to be touched in order for error message to be displayed:
get errorMessage() {
for (let propertyName in this.control.errors) {
if (this.control.errors.hasOwnProperty(propertyName) &&
this.control.touched) { // this line
return ValidationService.getValidatorErrorMessage(propertyName, this.control.errors[propertyName]);
}
}
return null;
}
If you remove this.control.touched, validation will be performed as you type. But this also will result in required messages being displayed right away. Combination I prefer most is to display error message in two cases: when user clicks on input field and then clicks somewhere else or when user starts typing which can be achieved with following condition:
if (this.control.errors.hasOwnProperty(propertyName) &&
this.control.dirty ||
this.control.touched)

Related

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

Angular validation for fields to be valid but not required

I have the following in my template:
<div class="form-group">
<label for="work_phone">Work Phone</label>
<input type="text"
class="form-control"
name="workPhone"
ng-class="{'borderRed': contactInformation.workPhone.$invalid && contactInformation.submitted}"
ng-model="controller.contactInformation.workPhone"
ng-pattern="/^\d+$/"
maxlength="10"
id="work_phone">
<small class="error"
ng-show="contactInformation.workPhone.$invalid && !contactInformation.workPhone.$pristine && contactInformation.submitted">
That's not a valid phone number (only numerics are allowed)!
</small>
</div>
Conditions:
1. If the field is blank/untouched, the form should stay valid.
2. If there is any value in the field then it should be validated against the regex provided in ng-pattern.
Looks very trivial. I know. But for some stupid reason, unable to find a solution
So if i understand your problem you want allow only numerics you can use this directive to block every other caracters :
.directive('onlyDigits', function () {
return {
require: 'ngModel',
restrict: 'A',
link: function (scope, element, attr, ctrl) {
function inputValue(val) {
if (val) {
var digits = val.replace(/[^0-9]/g, '');
if (digits !== val) {
ctrl.$setViewValue(digits);
ctrl.$render();
}
return parseInt(digits,10);
}
return undefined;
}
ctrl.$parsers.push(inputValue);
}
};
});
And add the directive to your input, it's faster and you haven't to use ng-pattern :
<input type="text"
class="form-control"
name="workPhone"
maxlength="10"
id="work_phone" onlyDigits>
Your form currently stays valid to begin, because you're checking for $pristine. Try using $setPristine() when the form is empty to reset it, so no longer gets the error class.
You may change your regex so that it allows empty strings:
ng-pattern="/^\d*$/"

Customise Sitecore RichTextEditor to add default wrapper

The front end (html and css) is set up such a way that for the description text from a Sitecore content field needs to have a <p> tag wrapped around it.
So by default the RTE wraps texts in a <p> tag = TRUE. BUT the catch is you will need to hit Enter or copy/paste multiple paragraphs.
How can we force Sitecore to add a P tag if it's just one line?
Fortunately, From the dll, one particular function caught my eye:
protected virtual void SetupScripts()
{
foreach (XmlNode node in Factory.GetConfigNodes("clientscripts/htmleditor/script"))
this.Result.Scripts.AppendFormat("<script src=\"{0}\" language=\"{1}\"></script>\n", (object) XmlUtil.GetAttribute("src", node), (object) XmlUtil.GetAttribute("language", node));
}
NICE, eh? The developers of SITECORE are clever after all.
So I did this in the web.config,
<!— CLIENT SCRIPTS
These script files are included in the client, e.g. '<script src="/myscript.js" language="JavaScript"/>'
—>
<clientscripts>
<everypage />
<htmleditor>
<script src=”/assets/js/CustomRTE.js” language=”javascript”/>
</htmleditor>
</clientscripts>
And overrode scSendRequest function from EditorWindow.aspx.
window.scSendRequest = function(evt, command) {
var editor = scRichText.getEditor();
if (editor.get_mode() == 2) { //If in HTML edit mode
editor.set_mode(1); //Set mode to Design
}
var htmls = editor.get_html(true);
var regex = /<p[^>]*>.*?<\/p>/i;
var match = regex.exec(htmls);
if(match == null && htmls != null) {
htmls = "<p>" + htmls + "</p>";
}
//$("EditorValue").value = editor.get_html(true);
$("EditorValue").value = htmls;
scForm.browser.clearEvent(evt);
scForm.postRequest("", "", "", command);
return false;
}
AND YAY .. double rainbow and unicorn.
You could create your own custom solution for this requirement as well.
You could create a new pipeline event in the
<saveRichTextContent> pipeline - This could enable you to append the tag when you hit save on the rich text editor in sitecore
<renderField> pipeline - This could on the fly wrap your text into <p></p> tags while rendering the page, if the tag was not there in the original rtf text.
If you go for method 1: <saveRichTextContent>
You could add to the pipeline in web.config:
<processor type="Sitecore72.Classes.WrapRichTextInParagraphOnSave, Sitecore72" />
And you could use the following corresponding code:
namespace Sitecore72.Classes
{
public class WrapRichTextInParagraphOnSave
{
public void Process(SaveRichTextContentArgs args)
{
if (!(args.Content.Trim().StartsWith("<p>") && args.Content.Trim().EndsWith("</p>")))
args.Content = "<p>" + args.Content + "</p>";
}
}
}
Please note, that this pipeline gets triggered only when you use the Show Editor buttong of a rich text field:
If you go for method 2: <renderField>
To append to this pipeline you would use this config:
<processor type="Sitecore72.Classes.WrapRichTextInParagraphOnRender, Sitecore72" />
And you could use the following corresponding code:
namespace Sitecore72.Classes
{
public class WrapRichTextInParagraphOnRender
{
public void Process(RenderFieldArgs args)
{
if (args.FieldTypeKey == "rich text" && !(args.Result.FirstPart.Trim().StartsWith("<p>") && args.Result.FirstPart.Trim().EndsWith("</p>")))
args.Result.FirstPart = "<p>" + args.Result.FirstPart + "</p>";
}
}
}
For both these, ensure you add reference to Sitecore.Kernel.dll and HtmlAgilityPack.dll. Both of these are available with the sitecore package solution.

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>

Tinymce editor gallery plugin Regexp problem?

I am using tinymce editor for inserting contents to mysql.
I have changed wordpress gallery editor plugin according to my system.
If there is gallery code in content. I convert this code to a symbolic photo, so that user understand there is a gallery , in stead of seeing a code. Like wordpress does.
If there is only 1 gallery in content, i convert this code to image successfully, but if there is more than 1 gallery it fails.
How can i convert all {gallery} code into a symbolic image before saving to db and convert these photos back to {gallery} code again while inserting or updating into mysql.
I am so bad on regular expression.
I think do_gallery RegExp has mistake. How should i change this.
initalising editor like:
ed.onBeforeSetContent.add(function(ed, o) {
ed.dom.loadCSS(url + "/css/gallery.css");
o.content = t._do_gallery(o.content);
});
ed.onPostProcess.add(function(ed, o) {
if (o.get)
o.content = t._get_gallery(o.content);
});
My "do and get gallery" codes like that:
_do_gallery : function(co) {
return co.replace(/\{gallery([^\]]*)\}/g, function(a,b){
var image = '<img src="gallery.gif" class="wpGallery mceItem" title="gallery'+tinymce.DOM.encode(b)+'" />';
console.log(image);
return image;
});
},
_get_gallery : function(co) {
function getAttr(s, n) {
n = new RegExp(n + '="([^"]+)"', 'g').exec(s);
return n ? tinymce.DOM.decode(n[1]) : '';
};
return co.replace(/(?:<p{^>}*>)*(<img[^>]+>)(?:<\/p>)*/g, function(a,im) {
var cls = getAttr(im, 'class');
if ( cls.indexOf('wpGallery') != -1 )
return '<p>{'+tinymce.trim(getAttr(im, 'title'))+'}</p>';
return a;
});
}
If Content is:
<p>Blah</p>
<p>{gallery Name="gallery1" id="82" galeryID="15" sizeId="6" galery_type="list"}</p>
<p>test</p>
this is ok
<img src="gallery.gif" class="wpGallery mceItem" title="gallery Name="tekne1" id="82" galeryID="15" sizeId="6" galery_type="liste"" />
But, if content is:
<p>Blah</p>
<p>{gallery Name="gallery1" id="82" galeryID="15" sizeId="6" galery_type="list"}</p>
<p>test</p>
<p>{gallery Name="gallery2" id="88" galeryID="11" sizeId="1" galery_type="slide"}</p>
<p>test2</p>
it logs
<img src="gallery.gif" class="wpGallery mceItem" title="gallery Name="gallery1" id="82" galeryID="15" sizeId="6" galery_type="list"}</p> <p>test</p> <p>{gallery Name="gallery2" id="88" galeryID="11" sizeId="1" galery_type="slide"" />
I hope i could explain my problem
Thank you.
I suspect that your original regex is a typo, looks like a missing Shift when you hit the ]. Try this:
/\{gallery([^\}]*)\}/g
Then the ([^\}]*) part will (greedily) eat up any sequence of characters that aren't }; your original one would consume any sequence of character that didn't include a ] and the result is that you'd grab everything between the first { and the last } rather than just grabbing the text between pairs of braces.