<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Custom widget that moves selected features from one source to another in ArcGIS Experience Builder Questions</title>
    <link>https://community.esri.com/t5/arcgis-experience-builder-questions/custom-widget-that-moves-selected-features-from/m-p/1647470#M20686</link>
    <description>&lt;P&gt;I found the solution in another post &lt;A href="https://community.esri.com/t5/arcgis-experience-builder-questions/fail-to-load-map-and-custom-widget/td-p/1518485" target="_self"&gt;HERE.&lt;/A&gt;&lt;/P&gt;&lt;P&gt;Basically added&amp;nbsp;&lt;STRONG&gt;&lt;SPAN&gt;"dependency"&lt;/SPAN&gt;&lt;SPAN&gt;:&amp;nbsp;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN&gt;&lt;STRONG&gt;"jimu-arcgis" to &lt;/STRONG&gt;manifest.json&lt;/SPAN&gt;&lt;/P&gt;</description>
    <pubDate>Tue, 02 Sep 2025 21:13:46 GMT</pubDate>
    <dc:creator>MatthewGalvanFire</dc:creator>
    <dc:date>2025-09-02T21:13:46Z</dc:date>
    <item>
      <title>Custom widget that moves selected features from one source to another</title>
      <link>https://community.esri.com/t5/arcgis-experience-builder-questions/custom-widget-that-moves-selected-features-from/m-p/1647457#M20683</link>
      <description>&lt;P&gt;Hello All,&amp;nbsp;&lt;/P&gt;&lt;P&gt;Problem: Widget works fine in builder, but "fails to load" in preview.&lt;/P&gt;&lt;P&gt;This is my first time creating a custom widget. My goal was to create a widget where a user can select points on a map and send them to another layer that is connected to the map. The widget will also have a field where they can give those selected points a name. All attributes will be copied from the selected points and inserted into the other layer. Settings.tsx&lt;/P&gt;&lt;LI-CODE lang="java"&gt;/** @jsx jsx */
import { React, jsx, DataSourceTypes, Immutable } from 'jimu-core'
import type { AllWidgetSettingProps } from 'jimu-for-builder'
import type { UseDataSource } from 'jimu-core'
import { DataSourceSelector } from 'jimu-ui/advanced/data-source-selector'
import { MapWidgetSelector } from 'jimu-ui/advanced/setting-components'
import { useState } from 'react'

export default function Setting(props: AllWidgetSettingProps&amp;lt;any&amp;gt;) {
  const [statusMessage, setStatusMessage] = useState('')

  // Current target layer (DataSource)
  const targetUseDs: UseDataSource[] = props.config.targetDataSource
    ? [props.config.targetDataSource]
    : []

  // Toggle target layer enabled
  const onToggleTargetEnabled = (enabled: boolean) =&amp;gt; {
    props.onSettingChange({
      id: props.id,
      config: props.config.set('useTargetDsEnabled', enabled)
    })
  }

  // Update target DataSource
  const onTargetDsChange = (useDataSources: UseDataSource[]) =&amp;gt; {
    if (!useDataSources || useDataSources.length === 0) {
      setStatusMessage('Please select a target layer')
      props.onSettingChange({
        id: props.id,
        config: props.config.set('targetDataSource', null)
      })
      return
    }

    setStatusMessage('')
    props.onSettingChange({
      id: props.id,
      config: props.config.set('targetDataSource', useDataSources[0])
    })
  }

  return (
    &amp;lt;div className="widget-setting"&amp;gt;
      &amp;lt;h5&amp;gt;Source Map Widget&amp;lt;/h5&amp;gt;
      &amp;lt;MapWidgetSelector
        useMapWidgetIds={Immutable(props.useMapWidgetIds ?? [])}
        onSelect={(ids) =&amp;gt; {
          props.onSettingChange({ id: props.id, useMapWidgetIds: ids })
        }}
      /&amp;gt;

      &amp;lt;h5 className="mt-3"&amp;gt;Target Layer&amp;lt;/h5&amp;gt;
      &amp;lt;DataSourceSelector
        widgetId={props.id}
        types={Immutable([DataSourceTypes.FeatureLayer])}
        useDataSources={Immutable(targetUseDs)}
        useDataSourcesEnabled={props.config.useTargetDsEnabled ?? true}
        onChange={onTargetDsChange}
        onToggleUseDataEnabled={onToggleTargetEnabled}
      /&amp;gt;

      {statusMessage &amp;amp;&amp;amp; (
        &amp;lt;div className="status-message" style={{ marginTop: 8, color: 'red' }}&amp;gt;
          {statusMessage}
        &amp;lt;/div&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  )
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;widget.tsx&lt;/P&gt;&lt;LI-CODE lang="python"&gt;/** @jsx jsx */
import { React, jsx, DataSourceManager,  } from 'jimu-core'
import type { FeatureLayerDataSource, DataRecord } from 'jimu-core'
import { useState } from 'react'
import { Button, TextInput, Alert } from 'jimu-ui'
import Graphic from '@arcgis/core/Graphic'

export default function MoveToStrikeTeamWidget(props) {
  const [strikeTeamName, setStrikeTeamName] = useState('')
  const [loading, setLoading] = useState(false)
  const [status, setStatus] = useState&amp;lt;{ type: 'success' | 'error' | 'warning'; message: string } | null&amp;gt;(null)

  const showStatus = (type: 'success' | 'error' | 'warning', message: string) =&amp;gt; {
    setStatus({ type, message })
    setTimeout(() =&amp;gt; { setStatus(null) }, 5000)
  }

  // Render fallback if configuration is missing
  if (!props.useMapWidgetIds?.length || !props.config?.targetDataSource) {
    return &amp;lt;div style={{ color: '#666' }}&amp;gt;Configure the source map widget and target layer in settings.&amp;lt;/div&amp;gt;
  }

  const moveSelectedFeatures = async () =&amp;gt; {
    if (!strikeTeamName.trim()) {
      showStatus('warning', 'Please enter a Strike Team Name.')
      return
    }

    setLoading(true)

    try {

      // Get all data sources as array
      const allDsArray = Object.values(DataSourceManager.getInstance().getDataSources())

      // Filter only FeatureLayerDataSources
      const sourceDsList = allDsArray.filter(
        ds =&amp;gt; ds.type === 'FeatureLayer' &amp;amp;&amp;amp; typeof ds.getSelectedRecords === 'function'
      ) as FeatureLayerDataSource[]

      if (!sourceDsList.length) {
        showStatus('error', 'No source FeatureLayer found in the selected map widget.')
        setLoading(false)
        return
      }

      // Collect selected records
      const selectedRecords: DataRecord[] = sourceDsList.flatMap(ds =&amp;gt; ds.getSelectedRecords())
      if (!selectedRecords.length) {
        showStatus('warning', 'No features selected in the source map.')
        setLoading(false)
        return
      }

      // Get target DataSource
      const targetUseDs = props.config.targetDataSource
      const targetDs = DataSourceManager.getInstance().getDataSource(targetUseDs.dataSourceId) as FeatureLayerDataSource

      if (!targetDs || !targetDs.layer) {
        showStatus('error', 'Target data source not ready.')
        setLoading(false)
        return
      }

      const targetLayer = targetDs.layer
      await targetLayer.when() // ensure layer is fully loaded

      // Prepare graphics for target
      const addFeatures: Graphic[] = selectedRecords.map(r =&amp;gt; {
        const json = r.toJson()
        return new Graphic({
          geometry: json.geometry,
          attributes: {
            ...json.attributes,
            StrikeTeamName: strikeTeamName
          }
        })
      })

      // Apply edits to target layer
      const addResults = await targetLayer.applyEdits({ addFeatures })
      if (!addResults.addFeatureResults || addResults.addFeatureResults.length === 0) {
        showStatus('error', 'Failed to add features to target layer.')
        setLoading(false)
        return
      }

      // Delete features from source layers
      for (const ds of sourceDsList) {
        const recordsToDelete = ds.getSelectedRecords()
        const sourceLayer = ds.layer
        if (recordsToDelete.length &amp;amp;&amp;amp; sourceLayer) {
          await sourceLayer.when()
          const deleteFeatures = recordsToDelete.map(r =&amp;gt; ({ objectId: Number(r.getId()) }))
          await sourceLayer.applyEdits({ deleteFeatures })
        }
      }

      showStatus('success', `Successfully moved ${addResults.addFeatureResults.length} feature(s) to StrikeTeamGroup.`)
      setStrikeTeamName('')

    } catch (err) {
      console.error('Runtime error in MoveToStrikeTeamWidget:', err)
      showStatus('error', 'Widget failed to load or move features. Check console.')
    } finally {
      setLoading(false)
    }
  }

  return (
    &amp;lt;div className="p-2"&amp;gt;
      &amp;lt;h4&amp;gt;Move to Strike Team&amp;lt;/h4&amp;gt;
      &amp;lt;TextInput
        placeholder="Enter Strike Team Name"
        value={strikeTeamName}
        onChange={e =&amp;gt; { setStrikeTeamName(e.target.value) }}
        className="mb-2"
      /&amp;gt;
      &amp;lt;Button
        type="primary"
        onClick={moveSelectedFeatures}
        disabled={loading}
        block
      &amp;gt;
        {loading ? 'Moving...' : 'Move Selected Features'}
      &amp;lt;/Button&amp;gt;

      {status &amp;amp;&amp;amp; (
        &amp;lt;Alert type={status.type} text={status.message} className="mt-2" /&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  )
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;Thanks in advance.&lt;/P&gt;&lt;P&gt;-Matthew&lt;/P&gt;</description>
      <pubDate>Tue, 02 Sep 2025 20:19:52 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-experience-builder-questions/custom-widget-that-moves-selected-features-from/m-p/1647457#M20683</guid>
      <dc:creator>MatthewGalvanFire</dc:creator>
      <dc:date>2025-09-02T20:19:52Z</dc:date>
    </item>
    <item>
      <title>Re: Custom widget that moves selected features from one source to another</title>
      <link>https://community.esri.com/t5/arcgis-experience-builder-questions/custom-widget-that-moves-selected-features-from/m-p/1647470#M20686</link>
      <description>&lt;P&gt;I found the solution in another post &lt;A href="https://community.esri.com/t5/arcgis-experience-builder-questions/fail-to-load-map-and-custom-widget/td-p/1518485" target="_self"&gt;HERE.&lt;/A&gt;&lt;/P&gt;&lt;P&gt;Basically added&amp;nbsp;&lt;STRONG&gt;&lt;SPAN&gt;"dependency"&lt;/SPAN&gt;&lt;SPAN&gt;:&amp;nbsp;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN&gt;&lt;STRONG&gt;"jimu-arcgis" to &lt;/STRONG&gt;manifest.json&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 02 Sep 2025 21:13:46 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-experience-builder-questions/custom-widget-that-moves-selected-features-from/m-p/1647470#M20686</guid>
      <dc:creator>MatthewGalvanFire</dc:creator>
      <dc:date>2025-09-02T21:13:46Z</dc:date>
    </item>
  </channel>
</rss>

