Bind "src" attiribute in audio tag within vue code - vue.js

try to bind src of audio tag invue code bur does not work ..
Note that object (surah) is api json object ..
this is my code :
<audio controls class="audio">
<source :src="'#/data/mp3/' + surah.source" type="audio/mpeg">
<p>عفوًا متصفحك لا يدعم تشغيل الأصوات، قم بتحديثه أو استخدم متصفح آخر.</p>
</audio>
rest of code work will (use api) except for this ..

Make sure the surah object is available in component's data
Make sure if the mp3 files are stored in a data/mp3 folder
Make shure the source proprety of surah object is a valid string that represents the name of mp3 file (Ex: file_audio.mp3)
try this example:
template:
<audio controls class="audio">
<source :src="`#/data/mp3/${surah.source}`" type="audio/mpeg">
<p>عفوًا متصفحك لا يدعم تشغيل الأصوات، قم بتحديثه أو استخدم متصفح آخر.</p>
</audio>
script
export default {
data() {
return {
surah: {
name: 'يونس',
Number: 10,
'Number of Verses': 109,
'Makki/Madani': 'مكية',
Theme: 'قصص الأنبياء',
source: '010.mp3',
},
}
}
}

Related

Shopware 6 Custom Component watch Plugin Config

I am new to Shopware 6 and to vue.js as well. I would like to have a text-field in my plugin's config.xml, which will be disabled if another value in the config is true/false. Is there an event to subscribe? Can this be reactive (change disable state by only clicking the switch without having to save?). The switch should be able to disable a variable amount of input fields so I would not prefer to build a component just containing the switch and a corresponding text-input. Have you guys any hint?
For example:
I tried something like:
watch: {
'PluginName.config.disableswitch' (){
console.log("changed")
},
'$PluginName.config.disableswitch' (){
console.log("changed")
},
'PluginName.config.disableswitch': {
handler() {
console.log("changed");
},
},
'$PluginName.config.disableswitch': {
handler() {
console.log("changed");
},
},
},
My first suggestion is to install the VueJS extension on your browser, then inspect the Vue elements to know what data they get from the parents (it's not much).
So to pass down the data you want we will have to do just a tiny bit of work.
First, create a new plugin, e.g. src/custom/plugins/DockwareSamplePlugin
Then we need to rewrite the top level setting module to pass the config references you mentioned in your watcher.
Create a file src/Resources/app/administration/src/component/field-bind/settings/index.js
const {Component} = Shopware;
import template from './sw-system-config.html.twig'
Component.override('sw-system-config', {
template
});
You guessed it, in the same directory, create a file called src/Resources/app/administration/src/component/field-bind/settings/sw-system-config.html.twig
{% block sw_system_config_content_card_field %}
<sw-inherit-wrapper
v-model="actualConfigData[currentSalesChannelId][element.name]"
v-bind="getInheritWrapperBind(element)"
:has-parent="isNotDefaultSalesChannel"
:inherited-value="getInheritedValue(element)"
:class="'sw-system-config--field-' + kebabCase(getElementBind(element).name)"
>
<template #content="props">
<sw-form-field-renderer
v-bind="getElementBind(element, props)"
:key="props.isInheritField + props.isInherited"
:disabled="props.isInherited"
:value="props.currentValue"
#input="props.updateCurrentValue"
#change="props.updateCurrentValue"
:actualConfigData="actualConfigData[currentSalesChannelId]"
:myConfig="config[index]"
/>
</template>
</sw-inherit-wrapper>
{% endblock %}
Most of it is a copy from the original except the actualConfigData & myConfig attributes. This will insure that these props are passed to every field/component you create in your src/Resources/config/config.xml file.
Here is an example of such file implementation:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/shopware/platform/master/src/Core/System/SystemConfig/Schema/config.xsd">
<card>
<title>#DockwareSamplePlugin# Settings</title>
<title lang="de-DE">#DockwareSamplePlugin# Einstellungen</title>
<input-field type="bool">
<name>customToggle</name>
<label>Config switch</label>
<specialType>disable</specialType><!-- this is an example of how we know what switch controls hiding -->
</input-field>
<component name="field-bind-text">
<name>customText</name>
<label>Text</label>
</component>
</card>
</config>
Next thing we need to create that component field-bind-text that gets shown/hidden.
Create a directory structure & file src/Resources/app/administration/src/component/field-bind/text/index.js
const {Component} = Shopware;
import template from './field-bind-text.html.twig'
Component.register('field-bind-text', {
template,
methods: {
getHideToggleName() {
return this.$attrs.myConfig.elements.find(element => element.config?.specialType === 'disable')['name']
}
},
computed: {
shouldDisable() {
return this.$attrs.actualConfigData[this.getHideToggleName()] ?? false
}
}
});
getHideToggleName - this gets the XML entry name I mentioned earlier, but you could also adjust to whatever you like it to be. Can create a custom component & look for that instead (e.g. element.config.componentName === 'my-component')
shouldDisable - this looks up the value of the XML toggle (by name)
Then the twig file src/Resources/app/administration/src/component/field-bind/text/field-bind-text.html.twig
<div class="some-class">
<sw-text-field :disabled="shouldDisable"></sw-text-field>
</div>
Oh, and dont forget to load it all with that src/Resources/app/administration/src/main.js file
import './component/field-bind/text'
import './component/field-bind/settings'
Alrighty! See, easy peazy lemon squeezie. Now you can quit & go back to working with mage2.

React Admin - FileInput that uploads to a single flat key instead of an object

In react admin, if you have a FileInput, it requires a child field, and stores the file URL inside the child field. So for example
{
"photo": {
"url": "https://url-to-image.com"
}
}
and the corresponding react admin code is
<FileInput source='photo' label='Photo' placeholder={<p>Drop your image file here</p>}>
<ImageField source='url' title='title' />
</FileInput>
I want to upload to a single key called photoUrl instead of a nested object photo.url, which would look like this:
{
"photoUrl": "https://url-to-image.com"
}
How can I do this? When I omit the ImageField, I get an error that a single child is expected. I tried leaving source="" empty for the imagefield but it still produces an error.
Any ideas?
Try passing parse and format functions to FileInput props
<FileInput
source='photoUrl'
label='Photo'
placeholder={<p>Drop your image file here</p>}
parse={p => p.url}
format={url => ({url})}
>
<ImageField source='url' title='title' />
</FileInput>
https://marmelab.com/react-admin/Inputs.html#transforming-input-value-tofrom-record

Vuejs & FilePond files is not working. How to transfer loaded file to an object?

I would like to use FilePond to Load images. But the current image in loading isn't transfered to my object. ( so i can use that object to send it to database ith axios)
My object is simply like that :
data:function() {
return {
image:'',
}}
Then, my FilePond component is like that:
<FilePond
name="test"
ref="pond"
:maxFiles="max || 1"
labelIdle="Drop files here..."
allowMultiple="false"
acceptedFileTypes="image/jpeg, image/png"
:files="image"
v-on:init="handleFilePondInit"/>
Thank you for you help if someone use FilePond with vuejs.
According to enter link description here data:image should be array object.
data: function() {
return {
image: ['']
};
},

Twitter typeahead.js not working in Vue component

I'm trying to use Twitter's typeahead.js in a Vue component, but although I have it set up correctly as tested out outside any Vue component, when used within a component, no suggestions appear, and no errors are written to the console. It is simply as if it is not there. This is my typeahead setup code:
var codes = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('code'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: contextPath + "/product/codes"
});
$('.typeahead').typeahead({
hint: true,
highlight: true,
minLength: 3
},
{
name: 'codes',
display: 'code',
source: codes,
templates: {
suggestion: (data)=> {
return '<div><strong>' + data.code + '</strong> - ' + data.name + '</div>';
}
}
});
I use it with this form input:
<form>
<input id="item" ref="ttinput" autocomplete="off" placeholder="Enter code" name="item" type="text" class="typeahead"/>
</form>
As mentioned, if I move this to a div outside Vue.js control, and put the Javascript in a document ready block, it works just fine, a properly formatted set of suggestions appears as soon as 3 characters are input in the field. If, however, I put the Javascript in the mounted() for the component (or alternatively in a watch, I've tried both), no typeahead functionality kicks in (i.e., nothing happens after typing in 3 characters), although the Bloodhound prefetch call is made. For the life of me I can't see what the difference is.
Any suggestions as to where to look would be appreciated.
LATER: I've managed to get it to appear by putting the typeahead initialization code in the updated event (instead of mounted or watch). It must have been some problem with the DOM not being in the right state. I have some formatting issues but at least I can move on now.
The correct place to initialize Twitter Typeahead/Bloodhound is in the mounted() hook since thats when the DOM is completely built. (Ref)
Find below the relevant snippet: (Source: https://digitalfortress.tech/js/using-twitter-typeahead-with-vuejs/)
mounted() {
// configure datasource for the suggestions (i.e. Bloodhound)
this.suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
identify: item => item.id,
remote: {
url: http://example.com/search + '/%QUERY',
wildcard: '%QUERY'
}
});
// get the input element and init typeahead on it
let inputEl = $('.globalSearchInput input');
inputEl.typeahead(
{
minLength: 1,
highlight: true,
},
{
name: 'suggestions',
source: this.suggestions,
limit: 5,
display: item => item.title,
templates: {
suggestion: data => `${data.title}`;
}
}
);
}
You can also find a working example: https://gospelmusic.io/
and a Reference Tutorial to integrate twitter typeahead with your VueJS app.

Difference between dojoAttachpoint and id

<div dojoType="dojo.Dialog" id="alarmCatDialog" bgColor="#FFFFFF" bgOpacity="0.4" toggle="standard">
<div class='dijitInline'>
<input type='input' class='dateWidgetInput' dojoAttachPoint='numberOfDateNode' selected="true">
</div>
how to show this dialog I tried dijit.byId('alarmCatDialog').show();
The above code is a template and I called dijit.byId('alarmCatDialog').show() from the .js file .
dojo.attr(this.numberOfDateNode) this code works and I got the data .but if I change dojoattachpoint to id then I try dijit.byId('numberOfDateNode') will not work;
Your numberOfDateNode is a plain DOM node, not a widget/dijit, i.e. javascript object extending dijit/_Widget, which is the reason you cannot get a reference to it via dijit.byId("numberOfDateNode"). Use dojo.byId("numberOfDateNode") instead and you are all set.
dojoAttachPoint or its HTML5 valid version data-dojo-attach-point is being used inside a dijit template to attach a reference to DOM node or child dijit to dijit javascript object, which is the reason dijit.byId('alarmCatDialog').numberOfDateNode has a reference to your <input type='input' class='dateWidgetInput' .../>.
The main reason to use data-dojo-attach-point is that:
you can create multiple instances of dijit and therefore your template cannot identify nodes/dijits by IDs as you will have multiple nodes/dijits with the same ID
it's an elegant declarative way, so your code won't be full of dijit.byId/dojo.byId.
It is important to keep track of what is the contents and which is the template of the dijit.Dialog. Once you set contents of a dialog, its markup is parsed - but not in a manner, such that the TemplatedMixin is applied to the content-markup-declared-widgets.
To successfully implement a template, you would need something similar to the following code, note that I've commented where attachPoints kicks in.
This SitePen blog renders nice info on the subject
define(
[
"dojo/declare",
"dojo/_base/lang",
"dijit/_Templated",
"dijit/_Widget",
"dijit/Dialog"
], function(
declare,
lang,
_Templated,
_Widget,
Dialog
) {
return declare("my.Dialog", [Dialog, _Templated], {
// set any widget (Dialog construct) default parameters here
toggle: 'standard',
// render the dijit over a specific template
// you should be aware, that once this templateString is overloaded,
// then the one within Dialog is not rendered
templateString: '<div bgColor="#FFFFFF" bgOpacity="0.4">' +// our domNode reference
'<div class="dijitInline">' +
// setting a dojoAttachPoint makes it referencable from within widget by this attribute's value
' <input type="input" class="dateWidgetInput" dojoAttachPoint="numberOfDateNode" selected="true">' +
'</div>' +
'</div>',
constructor: function(args, srcNodeRef) {
args = args || {} // assert, we must mixin minimum an empty object
lang.mixin(this, args);
},
postCreate: function() {
// with most overrides, preferred way is to call super functionality first
this.inherited(arguments);
// here we can manipulate the contents of our widget,
// template parser _has run from this point forward
var input = this.numberOfDateNode;
// say we want to perform something on the numberOfDateNode, do so
},
// say we want to use dojo.Stateful pattern such that a call like
// myDialogInstance.set("dateValue", 1234)
// will automatically set the input.value, do as follows
_setDateValueAttr: function(val) {
// NB: USING dojoAttachPoint REFERENCE
this.numberOfDateNode.value = val;
},
// and in turn we must set up the getter
_getDateValueAttr: function() {
// NB: USING dojoAttachPoint REFERENCE
return this.numberOfDateNode.value;
}
});
});