How organize data in vue component to one structure? - javascript

Maybe complex question but i want try...
In vue component, (which is modal window for administration slider with few slide types like video, image...) i want have whole modal structure in json object. So i was created baseTypeStructure (inputs common for all slide types), avalibleTypeStructure (inputs for specific slide type) and activeTypeStructure (complete inputs structure after pick some slide type)
But i am in vue (and js) pretty new and i have complications with reactivity...
So if you pick some slide type i bind activeTypeStructure from baseTypeStructure and specific type from avalibleTypeStructure. (by type key)
But i have problems with reactivity... On one side i need reactive behavior because there are input values... on other side there are informations about visibility... and if i change in activeTypeStructure visibility to true, that value is changed in avalibleTypeStructure if i make clone (without reactivity), every change slide type i do reset all values...
Can anybody help with this? Resolve it this way (as one json format for whole modal). Maybe absolute bad thinking?
data() {
return {
detailModalIsOpened: false,
loading: false,
action: '',
title: 'default',
baseTypeStructure: {
inputs: {
name: {
visible: true,
value: ''
},
type: {
visible: true,
value: '',
selected: [],
slideTypes: []
},
duration: {
visible: true,
value: 5000
},
image: {
inputs: {
imageFile: {
visible: false,
value: ''
}
}
},
video: {
inputs: {
videoFile: {
visible: false,
value: ''
}
}
}
}
},
avalibleTypeStructures: {
none: {},
image: {
// name: 'image',
inputs: {
imageFile: {
visible: true,
value: ''
}
}
},
video: {
// name: 'video',
inputs: {
videoFile: {
visible: true,
value: ''
}
}
}
},
activeTypeStructure: {},
}
}

Related

ReactJS - Function to bulk overwrite nested usestate variable

I have a nested dictionary object with the following structure:
const [fieldErrorMessage, setFieldErrorMessage] = useState({
signinEmail: {
show: false,
message: "Error",
},
signinPassword: {
show: false,
message: "Error",
},
signupEmail: {
show: false,
message: "Error",
},
signupPassword: {
show: false,
message: "Error",
},
signupRegistrationToken: {
show: false,
message: "Error",
},
});
I created a function which should take in an array of nested dictionaries (e.g., signinEmail, signinPassword, ...) and set their value for their show key to false (without changing the value for the message property).
Here is my function:
function hideFieldErrors(setter, fieldNameArray) {
fieldNameArray.forEach((fieldName) => {
setter((prevState) => ({
...prevState,
fieldName: {
...prevState.fieldName,
show: false,
},
}));
});
}
When I call it, the show values do not change. Why is that?
I'm calling it via this code:
hideFieldErrors(setFieldErrorMessage, [
"signinEmail",
"signinPassword",
"signupEmail",
"signupPassword",
"signupRegistrationToken",
]);
The way you have used fieldName is not working as you expected. variable name(which is a string) should be wrapped with square brackets to make it an accessible property.
Try like below.
function hideFieldErrors(setter, fieldNameArray) {
fieldNameArray.forEach((fieldName) => {
setter((prevState) => ({
...prevState,
[fieldName]: {
...prevState[fieldName],
show: false,
},
}));
});
}

PowerBI Embedded vertical scrollbar not visible

I have embedded a PowerBI report. This is the Javascript with the page setup.
For some reason I don't get a vertical scrollbar in my report. When I open it in the workspace online the scrollbars work just fine. I already tried switching between different 'View' options in PowerBi but that does not seem to make a difference.
<H2>PowerBI</H2>
<p><i>User: {{username}} | AccessLevel: {{access_level}}</i></p>
<div id="reportContainer" style="height: 80vh;"></div>
<script type="text/javascript">
window.onload = function () {
// Get models. models contains enums that can be used.
var models = window['powerbi-client'].models;
var embedConfiguration = {
type: 'report',
id: '{{txtembedreportid}}',
embedUrl: '{{txtreportembed}}',
tokenType: models.TokenType.Embed,
accessToken: '{{txtaccesstoken}}',
settings: {
layoutType: models.LayoutType.Custom,
customLayout: {
pageSize: {
type: models.PageSizeType.Widescreen,
}
},
panes:{
bookmarks: {
visible: false
},
fields: {
expanded: false
},
filters: {
expanded: false,
visible: false
},
pageNavigation: {
visible: true
},
selection: {
visible: true
},
syncSlicers: {
visible: true
},
visualizations: {
expanded: false
}
}
}
};
var $reportContainer = $('#reportContainer');
var report = powerbi.embed($reportContainer.get(0), embedConfiguration);
report.fullscreen();
}
</script>
Try adding the "displayOption" property with value "FitToWidth" in customLayout object, as this option will try to fit the report as per the total available size for the page and will introduce a scrollbar for the remaining part if necessary.
Also change "Widescreen" to "Custom" in pageSizeType object
After all changes, your embedConfiguration will become as following.
var embedConfiguration = {
type: 'report',
id: '{{txtembedreportid}}',
embedUrl: '{{txtreportembed}}',
tokenType: models.TokenType.Embed,
accessToken: '{{txtaccesstoken}}',
settings: {
layoutType: models.LayoutType.Custom,
customLayout: {
displayOption: models.DisplayOption.FitToWidth, // Add "FitToWidth"
pageSize: {
type: models.PageSizeType.Custom, // Change to "Custom"
}
},
panes:{
bookmarks: {
visible: false
},
fields: {
expanded: false
},
filters: {
expanded: false,
visible: false
},
pageNavigation: {
visible: true
},
selection: {
visible: true
},
syncSlicers: {
visible: true
},
visualizations: {
expanded: false
}
}
}
};
Refer docs: https://learn.microsoft.com/en-us/javascript/api/overview/powerbi/custom-layout

Javascript - set new property based on other properties within an array inside the object

Here is a data structure I'm working with
masterObject: {
Steps: [
{
step: {
required: false,
},
step: {
required: false,
},
step: {
required: false,
},
},
]
}
I'd like to loop through Steps array and check if all each step object contains propery required that is equal to false.
If all required steps are false I'd like to attach a property to the masterObject object of
masterObject.isObjectWithNoRequiredSteps = true;
which would look like this after the code runs
masterObject: {
Steps: [
{
step: {
required: false,
},
step: {
required: false,
},
step: {
required: false,
},
},
]
isObjectWithNoRequiredSteps: true
}
If theres an example where one of the step object required is true I'd like to set the new property to false
masterObject.isObjectWithNoRequiredSteps = false;
masterObject: {
Steps: [
{
step: {
required: true,
},
step: {
required: false,
},
step: {
required: false,
},
},
]
isObjectWithNoRequiredSteps: false
}
What is the best approach to setting this property on the higher level object?
The object inside Steps array has multiple attributes/keys with the same name step. This is not allowed in JavaScript. Consider changing your data structure as follows
masterObject: {Steps: [{
step1: { required: false, },
step2: { required: false, },
step3: { required: false, },
}, ] }
Now, to determine if each step inside Steps array is false, use following code
masterObject.isObjectWithNoRequiredSteps = Object.keys(masterObject.Steps[0]).reduce(function(result, nextStep){
const isRequired = masterObject.Steps[0][nextStep].required;
return !isRequired && result;
}, true);

Rally combobox doesn't work on click

I want to create combobox listing all the PortfolioItem/Feature filtered by Name. Here is my code
Ext.define('Rally.Dashboard', {
extend: 'Rally.app.App',
launch: function () {
if (this.down('#features')) {
this.down('#features').destroy();
}
var features = Ext.create('Rally.ui.combobox.ComboBox', {
itemId: 'features',
allowNoEntry: false,
storeConfig: {
model: 'PortfolioItem/Feature',
fetch: ['FormattedID', 'Name', 'ObjectID', 'UserStories'],
autoSelect: true,
pageSize: 100,
autoLoad: true,
filters: [this._getFilter()]
},
fieldLabel: 'Select Feature',
listeners: {
ready: function (combobox) {
if (combobox.getRecord()) {
this._onFeatureSelected(combobox.getRecord());
}
},
select: function (combobox) {
if (combobox.getRecord()) {
this._onFeatureSelected(combobox.getRecord());
}
},
scope: this
}
});
this.add(features);
},
_onFeatureSelected: function (feature) {
console.log('feature', feature.get('Name'));
},//_onFeatureSelected
_getFilter: function ()
{
return {
property: 'Name',
operator: 'Contains',
value: 'Feature'
}
}
});
Rally.launchApp('Rally.Dashboard', {
name: 'example'
});
When dashboard loads for first time, everything works correctly. But when i click the combobox, the combobox will be cleaned up, and in the log, it shows response error
"QueryResult": {"Errors": ["Could not parse: Could not find attribute \"_refObjectName\" on type PortfolioItems in the query segment \"_refObjectName\""], "TotalResultCount": 0, "StartIndex": 0, "PageSize": 0, "Results": []}}
Ah, the combobox. Unfortunately this component has had a rough life due to many, many varied usages across the product and a couple incompatible ExtJS upgrades over time.
There's a really nice Artifact Search combobox that I'd recommend using instead, as I think it handles a bunch of the weirdness (including typeahead search) for you:
var features = Ext.create('Rally.ui.combobox.ArtifactSearchComboBox', {
itemId: 'features',
allowNoEntry: false,
storeConfig: {
models: ['PortfolioItem/Feature'],
fetch: ['FormattedID', 'Name', 'ObjectID', 'UserStories'],
pageSize: 100,
autoLoad: true // or false if you want to wait to load until click
},
fieldLabel: 'Select Feature',
listeners: {
ready: function (combobox) {
if (combobox.getRecord()) {
this._onFeatureSelected(combobox.getRecord());
}
},
select: function (combobox) {
if (combobox.getRecord()) {
this._onFeatureSelected(combobox.getRecord());
}
},
scope: this
}
});

Trouble with Sencha Touch MVC

I'm trying to learn how to use Sencha Touch to build web apps. I've been following the tutorial Here and I am a bit stuck. Below have created one controller, two views and a model (All other code is copy & paste from the tutorial). The first view, Index works great. However if I try to access the second, it brings up a blank page, none of the toolbar buttons work and it doesn't fire the alert.
If I do comment out the line this.application.viewport.setActiveItem(this.editGyms);, the alert will fire, but obviously, it doesn't render the page.
I've looked at a couple other tutorials, and they seem to also be using the setActiveItem member to switch views.. Am I missing something, or do I have to somehow deactivate the first view to activate the second or something?
HomeController.js
Ext.regController('Home', {
//Index
index: function()
{
if ( ! this.indexView)
{
this.indexView = this.render({
xtype: 'HomeIndex',
});
}
this.application.viewport.setActiveItem(this.indexView);
},
editGyms: function()
{
if ( ! this.editGyms)
{
this.editGyms = this.render({
xtype: 'EditGymStore',
});
}
this.application.viewport.setActiveItem(this.editGyms);
Ext.Msg.alert('Test', "Edit's index action was called!");
},
});
views/home/HomeIndexView.js
App.views.wodList = new Ext.List({
id: 'WODList',
store: 'WODStore',
disableSelection: true,
fullscreen: true,
itemTpl: '<div class="list-item-title"><b>{title}</b></div>' + '<div class="list-item-narrative">{wod}</div>'
});
App.views.HomeIndex = Ext.extend(Ext.Panel, {
items: [App.views.wodList]
});
Ext.reg('HomeIndex', App.views.HomeIndex);
views/home/EditGymStore.js
App.views.EditGymStore = Ext.extend(Ext.Panel, {
html: 'Edit Gyms Displayed Here',
});
Ext.reg('EditGymStore', App.views.EditGymStore);
models/appModel.js
Ext.regModel('WOD', {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'wod', type: 'string' },
{ name: 'url', type: 'string' }
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title' }
]
});
Ext.regStore('WODStore', {
model: 'WOD',
sorters: [{
property: 'id',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'wod-app-localstore'
},
// REMOVE AFTER TESTING!!
data: [
{ id: 1, date: new Date(), title: '110806 - Title1', wod: '<br/><br/>Desc1</br><br/>' },
{ id: 1, date: new Date(), title: '110806 - Title1', wod: '<br/><br/>Desc2</br><br/>' }
]
});
viewport.js with toolbar
App.views.viewport = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
cardSwitchAnimation: 'slide',
scroll: 'vertical',
styleHtmlContent: true,
style: 'background: #d8e2ef',
dockedItems: [
{
xtype: 'toolbar',
title: 'The Daily WOD',
buttonAlign: 'right',
items: [
{
id: 'loginButton',
text: 'Login',
ui: 'action',
handler: function() {
Ext.Msg.alert('Login', "This will allow you to Login!");
}
},
{
xtype: 'spacer'
},
{
xtype: 'button',
iconMask: true,
iconCls: 'refresh',
ui: 'action',
handler: function() {
Ext.Msg.alert('Refresh', "Refresh!");
}
}]
},
],
});
Thanks for the help!!
In HomeController.js your action function (editGyms) is the same name as the variable you're using for your view (this.editGyms) so when it tries to setActiveItem(this.editGyms) its actually passing the controllers action function rather than the results of this.render({...})
Either change the name of the controller action or change the name of the variable you use to hold the view.. like
editGyms: function() {
if ( ! this.editGymView) {
this.editGymView = this.render({
xtype: 'EditGymStore',
});
}
this.application.viewport.setActiveItem(this.editGymView);
Ext.Msg.alert('Test', "Edit's index action was called!");
}
I am colleagues with the guy that wrote the tutorial you are referring to. You should add a comment on that post because I described your problem to him and he said that he knows the solution.
You can just add a link to this page so that you won't need to describe everything again.
Also he will (very) soon publish the 3rd part of that tutorial that will cover some similar things.

Categories

Resources