Access checkbox value of an item in an array - Sitecore - html

I cannot seem to get the value of a checkbox field of "NoIndexNoFollow" I have set in my content.
I have tried two of the follow code samples below.
1) I get FALSE for every item even if I check the box in the content editor.
foreach (var item in Model.SiteSearchResults)
{
Sitecore.Data.Fields.CheckboxField checkboxField = Sitecore.Context.Item.Fields["NoIndexNoFollow"];
if (checkboxField.Checked)
{ *CODE*}
}
2) Nothing populates here.
foreach (var item in Model.SiteSearchResults)
{
var toindex = Sitecore.Context.Item.Fields["NoIndexNoFollow"].ToString();
if (toindex == "1")
{ *CODE* }
}
I am getting no value from these items.....Not sure the right way to call a checkbox field even though either of these seem to be working for other examples I am looking at.

You can use extensions methods to make the method re-useable, but the key thing to take away from these solutions is utilising the utility function from Sitecore MainUtil.GetBool(checkboxField.Value, false);
using System;
using Sitecore;
using Sitecore.Data.Fields;
using Sitecore.Resources.Media;
namespace MyProject.Extensions
{
public static class FieldExtensions
{
public static bool IsChecked(this Field checkboxField)
{
if (checkboxField == null)
{
throw new ArgumentNullException(nameof(checkboxField));
}
return MainUtil.GetBool(checkboxField.Value, false);
}
}
public static class ItemExtensions
{
public static bool IsChecked(this Item item, ID fieldId)
{
var checkboxField = item.Fields[fieldId];
if (checkboxField == null)
{
throw new ArgumentNullException(nameof(checkboxField));
}
return MainUtil.GetBool(checkboxField.Value, false);
}
}
}
MyRendering.cshtml - using FieldExtensions
#using MyProject.Extensions
#model Sitecore.Mvc.Presentation.RenderingModel
#{
var noIndexNoFollow = Model.Item.Fields["NoIndexNoFollow"].IsChecked();
}
MyRendering.cshtml - using ItemExtensions
#using MyProject.Extensions
#using Sitecore.Mvc
#model Sitecore.Mvc.Presentation.RenderingModel
#{
var noIndexNoFollow = Model.Item.IsChecked(Model.Item.Fields["NoIndexNoFollow"].ID);
}

In your comment you wrote that Model.SiteSearchResults is a list of Sitecore ID.
You need to get item with this ID first and then check the value of the field using for example MainUtil.GetBool() method like:
foreach (var id in Model.SiteSearchResults)
{
if (Sitecore.MainUtil.GetBool(Sitecore.Context.Database.GetItem(id)["NoIndexNoFollow"], false))
{
<text>checked</text>
}
else
{
<text>not checked</text>
}
}

foreach (var item in Model.SiteSearchResults)
{
Database database = Sitecore.Context.Database;
Item myItem = database.GetItem(item.ItemId);
var fieldValue = myItem.Fields["NoIndexNoFollow"];
string noIndexValue = Convert.ToString(fieldValue);
}
So after thinking more about what you guys said, I came up with a little easier solution that works perfect for what I need. I really appreciate all the insights!

Related

Items are not filtered when the checkbox is unchecked

I have an array of four categories. I would like to put each individual category on a separate checkbox so that when clicked the array is filtered by a specific category. With the help of the code below, I want to do the following: if the array of checkboxes already has one of the categories, it will not be added the second time by clicking. Unfortunately, I don't have the filtering to remove the category when the checkbox is unchecked.
Please tell me what is wrong with? And please tell me, can this logic be written better? Thank you very much
public allProductsCategories: string[] = ["сars", "clothes", "home", "sport"];
public checkedCategoriesFilter: string[] = [];
public filterProductsCategoryCheckboxClick(event: Event): void {
const isCheckboxChecked = (<HTMLInputElement>event.target).checked;
const checkboxDataValue = (<HTMLInputElement>event.target).value;
if (isCheckboxChecked) {
if (!this.checkedCategoriesFilter.includes(checkboxDataValue)) {
this.checkedCategoriesFilter.push(checkboxDataValue)
} else {
return;
}
} else {
console.log('unchecked')
this.checkedCategoriesFilter.filter(category => category === checkboxDataValue);
}
console.log(this.checkedCategoriesFilter);
}
html
<div *ngFor="let checkboxCategory of allProductsCategories">
<input
type="checkbox"
[value]="checkboxCategory"
(change)="filterProductsCategoryCheckboxClick($event)"
>
</div>
Filter method return an array and need to store it in array.
Update your component.ts file code as given below:
public allProductsCategories: string[] = ['сars', 'clothes', 'home', 'sport'];
public checkedCategoriesFilter: any = [];
public filterProductsCategoryCheckboxClick(event: Event): void {
const isCheckboxChecked = (<HTMLInputElement>event.target).checked;
const checkboxDataValue = (<HTMLInputElement>event.target).value;
if (isCheckboxChecked) {
if (!this.checkedCategoriesFilter.includes(checkboxDataValue)) {
this.checkedCategoriesFilter.push(checkboxDataValue);
} else {
return;
}
} else {
console.log('unchecked');
this.checkedCategoriesFilter = this.checkedCategoriesFilter.filter(
(category) => {
return category !== checkboxDataValue;
}
);
}
console.log(this.checkedCategoriesFilter);
}

Custom ThingsBoard widget: set gauge value property

I need to edit the "Speed gauge" widget to show zero value when certain condition is met. This action should be executed in the onDataUpdated() function.
This widget inherits methods from the "TbAnalogueRadialGauge" class, which contains an update() method. If I'm not wrong, this would be its implementation:
update() {
if (this.ctx.data.length > 0) {
const cellData = this.ctx.data[0];
if (cellData.data.length > 0) {
const tvPair = cellData.data[cellData.data.length -
1];
const value = tvPair[1];
if (value !== this.gauge.value) {
this.gauge.value = value;
}
}
}
}
TbAnalogueRadialGauge extends TbAnalogueGauge. TbAnalogueGauge exends TbBaseGauge, where update() is implemented.
It seems to access the this.gauge.value property to update the gauge value. However, when I try to access this property from widget development IDE, it turns out to be undefined.
self.onDataUpdated = function() {
self.ctx.gauge.update();
console.log(self.ctx.gauge.value) // output: undefined
}
Does anyone have any ideas about how to access this property?
You need the following
self.ctx.gauge.gauge.value

CakePHP 4.x: How to access logged-in user info from within a custom Behavior?

I am trying to add a custom Behavior that is a clone of the default Timestamp. Mine is "Userstamp" adding the current user to audit-trail fields on all tables. At the point where Timestamp sets the field to "new FrozenTime($ts)", I want to set to "$identity->get('username')" or similar. I am having trouble reaching anything from Authentication/Authorization or Identity from within the Behavior.
I know that the information is there, somewhere. But what do I need to include in my Behavior class in order to retrieve it?
I found this link, but I don't see where to put the suggested code.
In my Table:
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->addBehavior('Userstamp');
.
.
.
}
Cake's timestamp Behavior:
public function timestamp(?DateTimeInterface $ts = null, bool $refreshTimestamp = false): DateTimeInterface
{
if ($ts) {
if ($this->_config['refreshTimestamp']) {
$this->_config['refreshTimestamp'] = false;
}
$this->_ts = new FrozenTime($ts);
} elseif ($this->_ts === null || $refreshTimestamp) {
$this->_ts = new FrozenTime();
}
return $this->_ts;
}
My userstamp Behavior:
public function userstamp($userstamp = null, bool $refreshUserstamp = false)
{
// Variations of this do not work, the Property is not available in UserstampBehavior
// $currentUser = $this->Authentication
// ->getIdentity()
// ->getIdentifier();
$currentUser = 'abc'; <<<<<<<<<<<<< Hard-coded temporarily
if ($userstamp) {
if ($this->_config['refreshUserstamp']) {
$this->_config['refreshUserstamp'] = false;
}
$this->_userstamp = $currentUser;
} elseif ($this->_userstamp === null || $refreshUserstamp) {
$this->_userstamp = $currentUser;
}
return $this->_userstamp;
}
Your Auth-Informations lives also in the session.
So you can access Session-stuff in a table-class like this:
(new Session)->read('Auth')
And therefore you give this information from a table-class to your Behaviour like this:
$this->addBehavior('Userstamp', ['user_info'=>(new Session)->read('Auth')]);
Then you can access this information in your behaviour:
public function initialize(array $config){
$this->user_info = $config['user_info'];
}
public function myFunction(){
// do something with $this->user_info
}

How to hide library source code in Google way?

For instance, I have a library and I would like to protect the source code to being viewed. The first method that comes to mind is to create public wrappers for private functions like the following
function executeMyCoolFunction(param1, param2, param3) {
return executeMyCoolFunction_(param1, param2, param3);
}
Only public part of the code will be visible in this way. It is fine, but all Google Service functions look like function abs() {/* */}. I am curious, is there an approach to hide library source code like Google does?
Edit 00: Do not "hide" a library code by using another library, i.e. the LibA with known project key uses the LibB with unknown project key. The public functions code of LibB is possible to get and even execute them. The code is
function exploreLib_(lib, libName) {
if (libName == null) {
for (var name in this) {
if (this[name] == lib) {
libName = name;
}
}
}
var res = [];
for (var entity in lib) {
var obj = lib[entity];
var code;
if (obj["toSource"] != null) {
code = obj.toSource();
}
else if (obj["toString"] != null) {
code = obj.toString();
}
else {
var nextLibCode = exploreLib_(obj, libName + "." + entity);
res = res.concat(nextLibCode);
}
if (code != null) {
res.push({ libraryName: libName, functionCode: code });
}
}
return res;
}
function explorerLibPublicFunctionsCode() {
var lstPublicFunctions = exploreLib_(LibA);
var password = LibA.LibB.getPassword();
}
I don't know what google does, but you could do something like this (not tested! just an idea):
function declarations:
var myApp = {
foo: function { /**/ },
bar: function { /**/ }
};
and then, in another place, an anonymous function writes foo() and bar():
(function(a) {
a['\u0066\u006F\u006F'] = function(){
// here code for foo
};
a['\u0062\u0061\u0072'] = function(){
// here code for bar
};
})(myApp);
You can pack or minify to obfuscate even more.
Edit: changed my answer to reflect the fact that an exception's stacktrace will contain the library project key.
In this example, MyLibraryB is a library included by MyLibraryA. Both are shared publicly to view (access controls) but only MyLibraryA's project key is made known. It appears it would be very difficult for an attacker to see the code in MyLibraryB:
//this function is in your MyLibraryA, and you share its project key
function executeMyCoolFunction(param1, param2, param3) {
for (var i = 0; i < 1000000; i++) {
debugger; //forces a breakpoint that the IDE cannot? step over
}
//... your code goes here
//don't share MyLibraryB project key
MyLibraryB.doSomething(args...);
}
but as per the #megabyte1024's comments, if you were to cause an exception in MyLibraryB.doSomething(), the stacktrace would contain the project key to MyLibraryB.

Encompassing object attributes with HTML and return in JSON

currently, i have written the following json search method.
[HttpPost]
public JsonResult Search(string videoTitle)
{
var auth = new Authentication() { Email = "abc#smu.abc", Password = "abc" };
var videoList = server.Search(auth, videoTitle);
String html = "";
foreach(var item in videoList){
var video = (Video)item;
html += "<b>"+video.Title+"</b>";
}
return Json(html, JsonRequestBehavior.AllowGet);
}
On screen, it returns this.
"\u003cb\u003eAge of Conan\u003c/b\u003e"
what should i do? The reason why i want to do this is so that i can make use of CSS to style tags so that it looks aesthetically better as the items drop down from the search input.
thanks
If you want to return pure HTML you shouldn't return JSON, you should rather use the ContentResult:
[HttpPost]
public ContentResult Search(string videoTitle)
{
var auth = new Authentication() { Email = "smu#smu.com", Password = "test" };
var videoList = server.Search(auth, videoTitle);
String html = "";
foreach(var item in videoList)
{
var video = (Video)item;
html += "<b>"+video.Title+"</b>";
}
return Content(html, "text/html");
}
You can request that with standard jQuery.get() and insert directly into DOM.